结构标签可以在其范围之前使用吗?

在以下示例中:

#include  #include  struct B b; struct B{int a;}; struct B; int main() { ba=3; printf("%d\n", ba); return 0; } 

结构标记B的文件范围从其第一个定义/声明struct B{int a;};struct B b;怎么样struct B b;B的范围之前参考B没有错误?

struct B; 结构类型声明或结构类型定义? 为什么它不与其他定义struct B{int a;};冲突struct B{int a;}; 在同一文件范围内?

struct B; 是结构声明 。 可以有相同对象的任意数量的声明。 对于具有多个可能声明的对象类型,声明必须兼容 – 例如,您可以为同一个函数使用多个原型,但是它们需要使用相同的参数和返回类型。 对于一个结构,只有一种方法可以在不定义它的情况下声明它,它只是说“有一个名为B的结构”。 所以重复struct B; 你想要多少次。

struct B{int a;}; 是一个结构定义 。 给定对象只能有一个定义。 对象的某些使用需要先前的定义,其他只需要事先声明。 例如,您可以定义一个变量,其类型是指向未定义结构的指针:

 struct S; struct S *p = NULL; 

但是您无法定义其类型为未定义结构的变量:

 struct S; struct S s = {0}; 

造成这种差异的原因是尚未定义的结构是不完整的类型 – 编译器没有大小的类型。 这不是定义指针​​的问题,但是定义不完整类型的对象是一个问题:编译器不知道需要多少内存。

在这一点上,你可能想知道为什么struct B b; 没关系 毕竟, struct B甚至没有被声明,更不用说定义了。

为什么它没问题的第一部分是struct B b; 声明结构B传递。 因此,当struct B需要用b做某事时,结构刚刚被声明。

结果struct B b;的第二部分是好的struct B b; 不完全是一个定义。 如果它是一个定义,那么编译器需要知道要保留多少空间,而不完整的类型则不行。 如果变量是在函数中定义的,那么会发生这种情况:

 void f(void) { struct B b; // error: storage size of 'b' isn't known } 

但是当struct B b; 它位于文件的顶层,这是一个暂定的定义 。 暂定的定义是声明; 为此,不需要定义结构。 当编译器到达文件末尾时,任何没有正确定义且需要定义的暂定定义都将成为定义。 此时,需要定义结构。 在您的示例程序中, b具有暂定定义,该定义在文件末尾成为正确的定义。

如果变量未使用,则不定义结构是可以的,因为如果不使用变量,则可以声明具有不完整类型的变量。

 struct B b; // end of file 

但如果变量以需要完整类型的方式使用,则必须在该点定义结构。

 struct B b; void f(void) { sizeof(b); // error: invalid application of 'sizeof' to incomplete type 'struct B' } struct B{int a;}; // too late 

问题:结构B b怎么样; 在B的范围之前参考B没有错误? 答案:来自http://c0x.coding-guidelines.com/6.7.2.3.html的第1471节,“如果forms为struct-or-union标识符的类型说明不是作为上述表单之一的一部分,并且没有其他标识符声明可见,然后它声明一个不完整的结构或联合类型,并将标识符声明为该类型的标记。“
因此,您可以在结构类型定义之前将struct标记用作前向声明。

问题:是结构B; 结构类型声明或结构类型定义? 为什么它不与其他定义struct B {int a;};冲突? 在同一文件范围内? 答案:来自第1472节中相同的上述链接,“如果forms为struct-or-union标识符枚举标识符的类型说明不是作为上述表单之一的一部分而发生,并且标识符作为标记的声明是可见,然后它指定与其他声明相同的类型,并且不重新声明标记。“

结构B; 是结构类型声明, struct B {int a;}; 是一种结构类型定义,它们是如何相互冲突的。 您可以选择使用typedef来消除混淆并显示对结构声明的更多可见性:

 typedef struct BB; struct B{ int a; }; B b;