Why should structure names have a typedef?
我见过源代码总是有一个结构的typedef,并且在任何地方都使用相同的typedef,而不是直接将结构名用作"struct sname"等。
这背后的原因是什么?这样做有什么好处吗?
- 在他的书《C编程专家》中,PetervanderLinden提出了这样一个例子:结构的typedef是无用的,您不应该费心。我喜欢这个。typedef所能做的就是在声明和原型等一些地方保存编写struct的操作。这不值得混淆。我想知道我什么时候必须使用->或.。typedef使这变得更难。
读Box b;比读struct boxtype b;容易。
1 2 3 4
| typedef struct _entry{
char *name;
int id;
} Entry, *EntryP; |
优势:在上面的typedef中,Entry和EntryP都是在struct _entry之外定义的。因此,可以使用EntryP firstentry代替struct _entry *firstentry,并且在心里解析起来要简单一些。
注意:它与结构名称不同,应该是typedef型的,但显然更容易阅读。此外,使用Entry *与EntryP完全取决于用户。
- 我通常反对像EntryP这样的typedef。C已经有了一个完美的方法来声明您想要的指针:Entry *firstentry。
- @哈格朗德:没什么好争论的。它完全是主观的,一个可能喜欢EntryP,另一个可能喜欢Entry *。
- 我同意这是主观的,但我不得不认为这是不推荐的,因为它抽象了一个事实,即firstentry是Entry *型,没有好的理由。虽然EntryP中的"p"是用来强调"指向"的,但它仍然不明确,而Entry *不是。在任何情况下,我相信你的行struct entry *firstentry应该是struct _entry *firstentry,注意下面的下划线
在C语言中这是一个奇怪的现象,结构标记名存储在不同的名称空间(符号表)中。C++语言摆脱了这种行为。typedef为全局命名空间中的结构类型创建别名。所以您不必在结构名称之前键入"struct"。
不知道里奇在定义这一行为时在吸烟。我猜想在早期版本的编译器中,解析器会出现某种问题。
- 我想这可能简化了第一个编译器中的内存分配,当所有的东西都必须适合128K或更少的数据空间时,这一点很重要。事实上,在最早的C编译器中,也有一个用于结构成员名称的全局命名空间。这意味着struct foo和struct bar不能同时拥有一个名为x的成员,这直接导致了一些C代码中常见的结构成员的标签样式(f_x和b_x。
- @戴夫:我认为你是对的。有人拿着结构成员的名字抽烟。时间太长了,我很久以前就把那个脑细胞放在了忽视的角落。哇,他为什么要这么做?B?
我喜欢用C语言:
1 2 3 4 5
| // in a"public" header file
typedef struct Example Example;
// in a"private" header or a source file
struct Example { ... }; |
像这样,我在代码中使用Example作为一个不透明的类型(即,我只能传递指向它的指针),除了实现其操作的代码,它可以看到它真正定义为什么。(您可以为不透明类型使用单独的名称,但没有真正的优势。)
它只是为了代码的可读性。typedef只是为数据类型提供新名称。不要给int任何你想用的方式命名它的地方,也不要给int任何你使用它的地方,你只需要用你给它的新名称替换它。同样的事情也适用于结构。
C中的非typefed结构名要求在所有使用类型名的地方都预加"struct",因此大多数人使用typedef为不需要一直预加struct关键字的类型创建新名称。
这样做的原因是代码可读性、类型的减少,以及可能的清晰性,但是typedef实际上会掩盖关于指针类型的信息。
老实说,TyWEFF为结构创建新名称的需要是一个遗物,遗憾的是C99没有遵循C++的线索并将其移除。
- 由于向后兼容,C99无法摆脱必须使用typedef才能摆脱struct。有很多像struct Foo {...} ; typedef ... Foo;这样的代码会停止编译。
它是一种信息隐藏形式,在创建不透明类型时很有用。请参阅此so链接以获得稍长的答案。
我实际上不使用typedef来表示结构。为什么?因为我会使用一些约定,比如s_前缀,来很容易地看到我正在查看的是什么类型的变量。
因为我使用了很多抽象数据类型,所以我想最好使用typedef,以便用户真正将其用作不透明类型。但是在实践中,我总是在实现中使用结构。