2010-11-16 182 views
4
gcc 4.4.4 c89 

我在我的头文件中有这个。foward typedef结构

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 */ 
} 

我有forwa rd声明了结构,因为我想隐藏内部元素。

不过,我让我的initialize_ports以下错误头文件:

expected ‘)’ before ‘*’ token 

我只是想知道我怎么能向前声明并能够通过结构作为参数?

非常感谢任何建议,

+0

你想隐藏内部元素,但现在你隐藏他们从你自己的代码。 'driver.h'需要访问'port.c'中的定义,这个定义需要放在一个更适合包含某个地方的文件中。 ('.c'文件通常包含代码,而不仅仅是类型定义。) – 2010-11-16 11:16:54

回答

5

正如其他答案已经注意到,您的可能更改struct_tagstruct struct_tag在原型。让你的代码编译的另一种方式是写

typedef struct struct_tag struct_tag; 

代替现有struct struct_tag;(即结合了前定义的类型定义)。那么确实允许你写

int initialize_ports(struct_tag *port) 

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

其他答案建议您打开结构的定义。这通常不是正确的答案 - 因为它会移除您尝试创建的抽象层。要好得多具备的功能(在port.c,即了解内部库),如:

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

即创建和自由的结构 - 事实上对其他操作(如读取/写入结构)。

+0

+1表示将initialize/create移动到port.c.技术上free_port不需要*去那里,但它是合乎逻辑的地方。 – JeremyP 2010-11-16 11:58:57

+0

谢谢:)最好有一个free_port()函数,因为端口结构本身可能包含指向其他结构的指针,这些结构在释放端口时也需要释放。 – psmears 2010-11-16 12:01:35

1

你会得到你不知道“口”的大小,所有它去是向前声明的错误。

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

+0

圆括号只用于'sizeof'类型,所以'sizeof * port'是完全有效的(除非如你所说,大小不是'在那个地方已知)。 – 2010-11-16 11:15:20

+0

@克里斯:谢谢......我不知道!修正了我的答案:) – Goz 2010-11-16 11:16:59

7

你应该使用:

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

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

1

sizeof操作者在编译时评价不运行时,因此在该行:

port = malloc(sizeof *port); 

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

解决方案包括:

  • 完全定义在头文件的类型。
  • define initialize_ports() in port.c after该结构已完全定义。
  • have initialize_ports()在运行时调用ports.c中定义的函数来获取Port_t的大小。

在任何情况下,你应该定义在头文件中的驱动程序initialize_ports()。除非你的编译器支持你使用它的inline_inline关键字。然而,这样的用法会使得代码不符合ISO C标准,因此可移植性较差,但是由于C++对关键字的标准支持,您可能会发现它作为大多数包含C++编译的C工具链的扩展,只要您不要使用过分严格的合规选项。

但是,您收到的错误消息是由于不同的原因。与单独使用C struct_tag的C++不同,它不代表某种类型(如果是,则不需要使用typedef!),则必须使用struct关键字。