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

Gar*_*ies 9 c struct typedef

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

typedef struct SomeStructTag {
    // struct members
} SomeStruct;
Run Code Online (Sandbox Code Playgroud)

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

typedef struct SomeStruct {
    // struct members
} SomeStruct;
Run Code Online (Sandbox Code Playgroud)

为类型使用特定名称并将typedef其用于不同类型名称有什么意义?

sup*_*cat 7

在大多数情况下,可以为两种目的使用相同的名称,没有任何问题。人们在代码中使用不同名称的做法可能源于 ANSI 标准化之前的日子,当时有很多编译器接受类似于 C 的大多数兼容方言。一些构造和特性几乎可以在任何编译器上运行,其他的可以运行在大多数情况下(但在很多情况下都失败了),而其他人只能在少数情况下工作。尽管标准多年来明确规定类型、结构标记和每个单独结构的成员有不同的命名空间,但早期的一些编译器并没有将所有这些命名空间识别为不同的、相当数量的代码被写成即使使用这样的编译器也应该可以工作,

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

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

typedef struct NODE_S NODE;
struct NODE_S {
  NODE *parent,*left,*right;
};
Run Code Online (Sandbox Code Playgroud)

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

  • @RichJahn:考虑`typedef struct foo { int x; } foo; 国际酒吧; ...无效测试(无效){ int foo; 富*酒吧;酒吧 = 0; }`,`test` 函数在书写时是有效的,或者`foo *bar` 语句被替换为`struct foo *bar;` 声明,但是有和没有`struct` 这个词的含义会有所不同。 (2认同)

Eri*_*son 6

在 typedef 和结构体之间使用不同的标签有一个功能原因。这是当你在做一个链表结构时,你的结构中的一个字段是一个指向正在定义的结构实例的指针。由于语句尚未完成,您不能在语句中使用 typedef 名称。

例如:

typedef struct {
    link_t *next;
    void   *data;
} link_t;
Run Code Online (Sandbox Code Playgroud)

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

typedef struct LL {
    struct LL *next;
    void      *data;
} link_t;
Run Code Online (Sandbox Code Playgroud)

并且 struct LL 在您使用它之前一行就被编译器知道了。