4
gcc 4.4.4 c89

我的头文件中有这个。

端口.h

struct struct_tag;

int initialize_ports(struct_tag *port);

在我的实现文件中,我有这个:

端口.c

typedef struct struct_tag {
    int port_id;
} Port_t;

在我的 driver.h 文件中,我有以下内容:

#include "port.h"
int initialize_ports(struct_tag *port)
{
    port = malloc(sizeof *port);
    /* do checking here */
}

我已经提前声明了结构,因为我想隐藏内部元素。

但是,我在头文件中的 initialize_ports 上收到以下错误:

expected ‘)’ before ‘*’ token

我只是想知道如何转发声明并能够将结构作为参数传递?

非常感谢您的任何建议,

4

4 回答 4

8

你应该使用:

int initialize_ports(struct struct_tag *port);
                     ^^^^^^

此外,前向声明给你一个不完整的类型,你不知道它的大小。如果你需要分配一个struct struct_tag你需要包含它的完整定义。create_struct_tag()或者,如果你想让它完全不透明,你可以使用一些功能。

于 2010-11-16T11:12:06.143 回答
6

正如其他答案所指出的,您可以在原型中更改struct_tag为。struct struct_tag让你的代码编译的另一种方法是编写

typedef struct struct_tag struct_tag;

代替您现有的struct struct_tag;(即将 typedef 与前向定义相结合)。那确实允许你写

int initialize_ports(struct_tag *port)

没有编译失败。但是,这仍然不是您想要的,因为调用者既不能分配这种类型的局部变量,也不能分配 malloc() ——因为他们不知道大小。

其他答案建议您应该打开结构的定义。这通常不是正确的答案 - 因为它删除了您尝试创建的抽象层。port.c拥有函数(在 中,即知道内部结构的库中)好得多,例如:

struct_tag *create_port(...);
void free_port(struct_tag *port)

即创建和释放结构——实际上也用于其他操作(例如读取/写入结构)。

于 2010-11-16T11:35:17.840 回答
2

运算符是在编译时而sizeof不是运行时评估的,所以在这一行:

port = malloc(sizeof *port);

编译器没有关于结构大小的信息。

解决方案包括:

  • 在头文件中完全定义类型。
  • 在结构完全定义后initialize_ports()port.c中定义。
  • initialize_ports()调用 ports.c 中定义的函数以Port_t在运行时获取大小。

在任何情况下,您都不应该initialize_ports()头文件 driver.h 中定义,除非您的编译器支持inlineor_inline关键字并且您使用它。然而,这种用法会使代码不符合 ISO C,因此可移植性较差,但是由于 C++ 对关键字的标准支持,您可能会在大多数包含 C++ 编译的 C 工具链中找到它作为扩展,只要您不会使用过于严格的合规选项。

但是,您收到的错误消息是出于不同的原因。与 C++ 不同,Cstruct_tag单独不代表一个类型(如果是,你就不需要typedef!),你必须使用struct关键字。

于 2010-11-16T11:30:43.530 回答
2

你会得到一个错误,因为你不知道“端口”的大小,因为它所要做的就是前向声明。

总之,你最好不要在这里使用前向声明,除非你还设置了一个常量值,即 sizeof "struct_tag" ...你很可能最好完全声明它。

于 2010-11-16T11:11:44.727 回答