【发布时间】:2013-01-14 21:25:19
【问题描述】:
给定以下代码:
typedef struct elementT {
int data;
struct elementT *next;
} element;
为什么必须在结构声明本身内执行struct elementT *next 而我不能执行element *next?是因为还没有声明吗?
【问题讨论】:
给定以下代码:
typedef struct elementT {
int data;
struct elementT *next;
} element;
为什么必须在结构声明本身内执行struct elementT *next 而我不能执行element *next?是因为还没有声明吗?
【问题讨论】:
typedef 仅在 struct 定义后发生。考虑以下代码;语法无效,但它希望它显示事物的顺序/优先级:
typedef (struct {
int field1, field2;
}) item;
即,struct{...} 是一个表示类型的“表达式”。 typedef 通过给它一个名字来操作那个类型。
相比之下,
struct foo {
foo *next;
};
之所以起作用,是因为 C 的两个特殊规则:struct <name> 不仅定义了一个类型,而且还给它一个 struct 标记,并且该标记在 struct 声明的其余部分中立即可见(对于显而易见的原因:如果没有这些规则,链表、树等实现起来会非常痛苦)。
【讨论】:
因为C这么说:
(C99, 6.2.1p7) "[...] 任何其他标识符的范围都在其声明符完成后开始。"
【讨论】:
struct defn 中,element 和 element* 都不是不完整的类型——它是一个完全未知的类型名称。
名称 elementT 是类型名称 struct elementT 的一部分,一旦编译器看到两个标记 struct elementT,就会变得可见(作为不完整的类型),因此您可以在结构定义。
名称element 是一个typedef 名称,直到出现标识符element 才可见,该标识符位于结构的结尾(结束})之后定义;因此你不能在结构定义中使用它,只是因为它还不存在。
我个人的偏好(很多非常聪明的人在这一点上与我不同)根本不使用typedef。该类型已经有了一个很好的名字,struct ElementT;为什么要添加第二个?我只想写:
struct element {
int data;
struct element *next;
};
并将类型称为struct element。
如果你觉得为类型使用一个单词名称就足够有用了,当然,你仍然可以使用 typedef。请记住,直到声明结束后 typedef 名称才可见。并且没有必要使用两个不同的标识符:
typedef struct element {
int data;
struct element *next;
} element;
现在您可以将类型称为struct element 或element。
(请注意,C++ 有不同的规则;它有效地为struct(或union、class 或enum)类型创建了一个隐式类型定义。在C++ 中,typedef 是不必要但无害的.)
【讨论】:
如果将结构声明与其定义分开,则可以实现此行为:
struct ElementT; // not strictly needed
typedef struct ElementT element; // this declares "struct ElementT" as well
struct ElementT
{
element * next;
};
【讨论】:
ElementT,编译器不会抱怨;它将使 element 成为从未完成的不完整类型的 typedef。