forward typedef结构

时间:2010-11-16 11:07:28

标签: c struct typedef forward-declaration

gcc 4.4.4 c89

我的头文件中有这个。

port.h

struct struct_tag;

int initialize_ports(struct_tag *port);

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

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 个答案:

答案 0 :(得分:7)

您应该使用:

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

此外,前向声明会为您提供不完整类型,您不知道其大小。如果您需要分配struct struct_tag,则需要包含完整定义。或者,如果要使其完全不透明,可以使用一些create_struct_tag()函数。

答案 1 :(得分:5)

正如其他答案所述,您可以在原型中将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)

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

答案 2 :(得分:1)

你会得到一个错误,因为你不知道“端口”的大小,因为所有它必须继续是前向声明。

总之,除非你还设置一个大小为“struct_tag”的常量值,否则你最好不要在这里使用前向声明...你最有可能只是完全声明它。

答案 3 :(得分:1)

编译时而非运行时评估sizeof运算符,所以在以下行:

port = malloc(sizeof *port);

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

解决方案包括:

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

在任何情况下,除非您的编译器支持initialize_ports()inline关键字,否则您应该在头文件driver.h中定义_inline 你使用它。然而,这样的使用会使代码不符合ISO C,因此不太便于移植,但是由于C ++对关键字的标准支持,您可能会发现它是包含C ++编译的大多数C工具链的扩展,只要你没有使用过于严格的合规选择。

但是,您收到的错误消息是出于其他原因。与C中的C ++不同,{C} {1}}不代表某种类型(如果有,则不需要struct_tag!),您必须使用typedef关键字。