为什么为结构使用不同的标记和typedef?

在C代码中,我看到了以下内容:

typedef struct SomeStructTag { // struct members } SomeStruct; 

我不清楚为什么这有什么不同:

 typedef struct SomeStruct { // struct members } SomeStruct; 

使用特定名称的类型和类型将其定义为不同的类型名称有什么意义?

在大多数情况下,可以使用相同的名称用于两种目的而没有任何问题。 在代码中使用不同名称的人的做法可能源于ANSI标准化之前的日子,当时有许多编译器接受了类似C的东西的大多数兼容方言。一些构造和特性几乎适用于任何编译器,其他的可以工作在大多数情况下(但在很大数量上失败),其他人只能在少数人身上工作。 虽然标准已经多年明确要求类型,结构标签和每个单独结构的成员有不同的命名空间,但是早期的一些编译器并没有将所有这些命名空间识别为不同的,相当多的代码写的,即使有这样的编译器也应该可以工作,而且人们倾向于编写类似于他们见过的其他代码的代码。

我认为使用今天规则给出的相同标识符的最强烈反对意见是不同标识符应该看起来不同的原则,并且通常应避免为给定目的使用两个语义等效标识符。 如果在它们之间存在一些明确的语义区别(例如“至少32位的最快类型”与“完全32位”类型),则可以将两个不同的标识符用于某种目的,但是使用两个不同的代码并不好用于相同目的的标识符基本上是随机的。 如果一个声明typedef struct FOO {...} FOO; ,然后struct FOOFOO将是不同的标识符,看起来好像它们应该是可互换的。 如果存在特定情况,其中一个应该使用一个或另一个并且名称是不同的,那么键入struct不应该,或反之,将导致编译错误。 如果名称匹配,事情就会编译,并且不会警告名称的使用与其他地方的使用不一致。

顺便提一下,尽管struct标签是全局可用的,但通常不需要多次使用任何标签。 即使结构应该包含自引用指针,也可以在ANSI C中声明它:

 typedef struct NODE_S NODE; struct NODE_S { NODE *parent,*left,*right; }; 

除了声明typedef名称的特定行之外,不必将类型称为struct NODE_S 。 在其他任何地方,人们可以直接使用typedef名称。

原因是struct标签和typedef名称在C中的不同名称空间中。您只能在关键字struct,之后使用struct标签struct,因此知道哪个是哪个是很方便的。

在C ++中,它们位于相同的命名空间中,因此不会出现问题。 这也意味着你的第二个例子可能不是合法的C ++。 您的第一个示例在两种语言中都是合法的

在typedef和struct之间使用不同的标记有一个function性原因。 这是在您执行链表结构时,其中结构中的一个字段是指向正在定义的结构的实例的指针。 由于语句尚未完成,因此您无法在语句中使用typedef名称。

例如:

 typedef struct { link_t* next; void* data; } link_t; 

将无法工作,因为您在编译器看到符号之前尝试使用link_t。 相反,你这样写:

 typedef struct LL { struct LL* next; void* data; } link_t; 

在使用之前,struct LL在编译器中已知一行。

C标准中没有理由为标签和类型使用不同的名称。 它们不能相互干扰,因为它们位于不同的名称空间中,不能在同一个地方使用。

因此,使用不同名称的唯一理由是人类心理学。 虽然其他答案表明对标签和类型使用不同的名称使得在代码中更容易发现它们,但是从来没有任何歧义,因为结构标记名称仅出现在struct之后,并且只有结构标记名称出现在struct之后。 更重要的是,如果它们是相同的,你不能意外地使用你想要的另一个。 所以不需要使用不同的名称。

C ++采用结构标签作为类名的事实表明,没有必要存在任何差异。

关键是SomeStruct将是一个正确的类型名称。 所以你不必输入

 struct SomeStructTag my_struct; 

在声明中:

 SomeStruct my_struct; 

除此之外,恕我直言,附加到名称的_t代表类型,而不是标签。