C Typedef和Struct问题

时间:2009-07-10 17:37:43

标签: c struct namespaces typedef

这两个声明之间有什么区别,并且优先于另一个声明?

typedef struct IOPORT {  
    GPIO_TypeDef* port;  
    u16           pin;  
} IOPORT;  

typedef struct {  
    GPIO_TypeDef* port;  
    u16           pin;  
} IOPORT;  

5 个答案:

答案 0 :(得分:15)

第一个允许您在struct中使用IMPORT来引用相同类型的对象。在链接列表等情况下非常有用,其中节点必须引用节点。

答案 1 :(得分:8)

至于首选哪种样式,我更喜欢第一种样式(结构标记中的名称和结构的typedef),因为除了源文件中的更多字符之外没有任何缺点。我的IDE的struct snippet在两个地方都删除了名称,所以我总是得到一个typedef'ed结构名称和一个struct标签名称。

您可以获得一些小的好处:

  • struct STRUCTNAME”可用于声明指向struct
  • 中结构的指针
  • 只需在C或C ++代码中使用STRUCTNAME即可逃脱。
  • 你可以防止C ++中的一个奇怪现象,即在没有错误或警告的情况下将结构名称用于另一个对象

但是,如果我碰巧手动输入结构定义,我常常懒得忽略声明一个或另一个名字。

答案 2 :(得分:8)

C有四个不同的命名空间,其中结构标记命名空间就是其中之一。因此:

struct foo { int bar; };

在一般意义上没有定义新类型。当你只有一个结构标记时,你需要在对象声明中添加关键字'struct',如下所示:

foo b; /* error */
struct foo b; /* correct */

此外,您可以在定义中立即实例化一个新对象,如下所示:

struct foo { int bar; } baz;

其中baz是结构类型为foo的对象。但是,人们经常希望将结构定义为新类型,以节省一些写作。完整类型不引用结构标记,因此您可以在声明期间省略'struct'前缀。

typedef struct foo { int bar; } baz;

仍然允许您使用'struct foo'声明对象,因为foo是struct标记。但现在它被提升为“普通”类型命名空间中的完整类型,其中它被称为类型baz。因此,对于typedef,'baz'字段具有不同的语义。

除非你需要在其内部声明指向结构类型的指针(链表,树结构),否则省略它。添加一个不需要的只会污染命名空间。

答案 3 :(得分:0)

第一个示例允许您将内部对象用于链接列表和树(如Victor points out)。第二个是匿名类型的一个例子,经验教导的所有编译器都没有很好的表现。所以可能推荐第一种方法。如果您不关心结构能够引用自身,那么您总是可以给它一个不太可能像__SOMEPREFIX_IOPORT__那样冲突的名称。

答案 4 :(得分:0)

出于可读性考虑,最好以以下形式表示原始示例:

typedef struct IOPORT_t {  
    GPIO_TypeDef* port;  
    u16           pin;  
} IOPORT; 

....强调类型和实例之间的区别。

此外,如果您要添加初始化程序,则可以执行以下操作:

typedef struct IOPORT_t {  
    GPIO_TypeDef* port;  
    u16           pin;  
} IOPORT;

struct IOPORT_t IOPORT2 = {
    .port = NULL,
    .pin = 25
  };

或者您可能会丢失typedef来直接对其进行初始化:

struct IOPORT_t {  
    GPIO_TypeDef* port;  
    u16           pin;  
} IOPORT = {
    .port = NULL,
    .pin = 24
  };

struct IOPORT_t IOPORT2 = {
    .port = NULL,
    .pin = 25
  };