例如考虑:
struct strct
{
data member_1;
data member_2;
......
};
编译器何时识别
struct strct
作为数据类型? 是在执行行
之后struct strct
? 或者在遇到结构定义的右括号之后?
答案 0 :(得分:8)
声明不会“执行”。
阅读后
struct strct {
编译器将struct strct
识别为不完整类型,这是一种不知道其大小的类型。由于您可以使用指向不完整类型的指针,因此您可以编写如下内容:
struct strct {
struct strct *next; // <- allowed, a pointer doesn't need the size of the object pointed to
int foo;
};
结构声明的“主体”完成后,struct strct
是完整类型,因此您可以声明该类型的变量(必须知道该大小)。
附注:您可以在标签后面用您的声明停止:
struct strct;
因此,让编译器知道不完整类型 struct strct
。这也称为前向声明。当然,只有在某处(可能是模块中的私有)具有完整声明时才有意义。在C中实现OOP代码时,这用于信息隐藏。例如,您只需公开声明这样的内容:
struct strct;
struct strct *strct_create(void);
strct_foo(struct strct *self);
strct_bar(struct strct *self, int x);
[...]
并在实现这些功能的文件中使用{em>完整声明struct strct
答案 1 :(得分:5)
名称struct strct
一出现在代码中即可查看。这允许您创建指向结构的指针作为结构的成员,如下所示:
struct mystruct {
int val;
struct mystruct *next;
};
在定义next
成员时,struct mystruct
被视为不完整。这很好,但是因为允许指向不完整类型的指针。
一旦遇到结构的右括号,结构就被认为是完整的,你可以定义它的实例。
另一方面,如果你试图这样做:
struct mystruct {
int val;
struct mystruct next;
};
由于结构不能包含自身,因此无效。
您还可以创建如下结构的转发声明:
struct mystruct;
这也会创建一个不完整的类型,并且可以允许您有两个相互引用的结构:
struct mystruct1;
struct mystruct2 {
int val;
struct mystruct1 *other;
};
struct mystruct1 {
int val;
struct mystruct2 *other;
};