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