【问题标题】:C Typedef and Struct QuestionC Typedef和结构问题
【发布时间】:2009-07-10 17:37:43
【问题描述】:
这两种声明有什么区别,一种优于另一种?
typedef struct IOPORT {
GPIO_TypeDef* port;
u16 pin;
} IOPORT;
typedef struct {
GPIO_TypeDef* port;
u16 pin;
} IOPORT;
【问题讨论】:
标签:
c
struct
namespaces
typedef
【解决方案1】:
第一个允许您在结构中使用 IOPORT 来引用相同类型的对象。在节点必须引用节点的链接列表等情况下很有用。
【解决方案2】:
C 有四个不同的命名空间,其中结构标签命名空间是其中之一。因此:
struct foo { int bar; };
没有定义一般意义上的新类型。当您只有一个结构标记时,您需要在对象声明中添加关键字“struct”,如下所示:
foo b; /* error */
struct foo b; /* correct */
此外,您可以像这样在定义中立即实例化一个新对象:
struct foo { int bar; } baz;
其中 baz 是结构类型 foo 的对象。但是,人们经常想将结构定义为一种新类型,以节省一些文字。完整类型不引用结构标记,因此您可以在声明期间省略“结构”前缀。
typedef struct foo { int bar; } baz;
仍然允许您使用 'struct foo' 声明对象,因为 foo 是 struct 标记。但现在它被提升为“普通”类型命名空间中的完整类型,称为 baz 类型。因此,对于 typedef,“baz”字段具有不同的语义。
除非您需要在其内部声明指向结构类型的指针(链表、树结构),否则请忽略它。添加一个不需要的只会污染命名空间。
【解决方案3】:
至于首选哪种样式,我更喜欢第一种样式(名称在结构标记中和作为结构的 typedef)只是因为除了源文件中的更多字符之外没有其他缺点。我的 IDE 的 struct sn-p 在这两个地方都删除了名称,所以我总是得到一个 typedef 的结构名称和一个结构标记名称。
您可以获得一些小好处:
- “
struct STRUCTNAME”可用于在结构中声明指向结构的指针
- 您只需在 C 或 C++ 代码中使用 STRUCTNAME 即可摆脱困境
- 您可以防止 C++ 中潜在的(即使在实践中非常罕见)怪异与用于另一个对象的结构名称有关,而不会出现错误或警告
但是,如果我碰巧手动输入了结构定义,我经常会懒惰地忽略声明一个或另一个名称。
【解决方案4】:
第一个示例允许您将对象内部用于链接列表和树(如Victor points out)。第二个是匿名类型的一个例子,经验表明它在所有编译器中都表现不佳。所以可能推荐第一种方法。如果您不关心结构是否能够引用自身,您始终可以给它起一个不太可能发生冲突的名称,例如 __SOMEPREFIX_IOPORT__。
【解决方案5】:
为了便于阅读,最好以如下形式表达原始示例:
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
};