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

时间:2013-12-11 23:33:40

标签: c struct typedef

在C代码中,我见过以下内容:

typedef struct SomeStructTag {
    // struct members
} SomeStruct;

我不清楚为什么会有这样的不同:

typedef struct SomeStruct {
    // struct members
} SomeStruct;

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

5 个答案:

答案 0 :(得分:4)

在大多数情况下,可以使用相同的名称来实现这两个目的而没有任何问题。在代码中使用不同名称的人的做法可能源于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名称。

答案 1 :(得分:2)

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

例如:

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

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

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

和struct LL在使用之前已为编译器所知。

答案 2 :(得分:1)

原因是struct标记和typedef名称位于C中的不同名称空间中。您只能在关键字struct后使用struct,标记,因此它非常方便知道哪个是哪个。

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

答案 3 :(得分:0)

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

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

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

答案 4 :(得分:-2)

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

struct SomeStructTag my_struct;

在声明中:

SomeStruct my_struct;

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