嵌套结构

以下代码在C ++编译器上编译。

#include int main() { struct xx { int x; struct yy { char s; struct xx *p; }; struct yy *q; }; 

使用C编译器编译时,行为会有什么不同吗?
即会有任何编译器错误?

你的post中的代码显然是不完整的,只是声明,所以很难说出任何结论。

明显不同的是,在C ++中,内部结构类型将是外部结构类型的成员,而在C语言中,两种结构类型将是相同(封闭)范围的成员。 (顺便说一下,你打算在main地方声明它们吗?)。

换句话说,在C ++中,后面的代码必须将结构称为xxxx::yy ,而在C中它们只是xxyy 。 这意味着对于C和C ++,进一步的代码看起来会有所不同,如果它在C ++中编译,它将无法在C中编译,反之亦然。

补充: C语言禁止在其他结构中声明结构类型而不声明该类型的成员。 因此, struct yy声明在C中是非法的,并将生成编译器诊断消息。 如果您希望代码在C和C ++中合法化,则必须将struct yy声明与某些数据成员声明相结合。 在你的情况下,可能是指针q

 struct xx { int x; struct yy { char s; struct xx *p; } *q; }; 

上述内容在C和C ++中都是合法的(考虑到我之前解释的差异),但您的原始声明在C中是不合法的。

以下是一些变化(感谢AndreyT):

显然你必须改变标题才能进行编译。 但即便如此,正如AndreyT指出的那样,这似乎不是标准的C. 尽管如此,像gcc这样的一些编译器仍会按预期编译它,并且只发出警告。 同样, 微软似乎也没有严格地解释标准:

“当结构声明是另一个结构或联合的成员时,也可以在没有声明者的情况下指定结构声明”

要使其成为标准C,您必须将“struct yy”声明转换为定义。 那么你的代码在C和C ++中都是有效的。 为了说明发生了什么,我把它重写了一下,在我看来,更加易于理解的时尚,并对正在发生的事情进行了一些测试。

 #include #include typedef struct xx xx; typedef struct yy yy; struct yy{ char s; xx *p;}; struct xx{ int x; yy *q;}; int main(){ xx test; test.q = (yy*)malloc(sizeof(yy)); test.q->s = 'a'; test.q->p = (xx*)malloc(sizeof(xx)); test.q->p->x = 1; test.q->p->q = (yy*)malloc(sizeof(yy)); test.q->p->q->s = 'b'; printf("s: %c\n", test.q->s); printf("x: %d\n", test.q->p->x); printf("s: %c\n", test.q->p->q->s); return 0; } 

你可以很容易地看到,你有一个带有指向xx的结构的struct yy,而struct xx有一个指向yy的指针。 这相当于ansi-C中可以写成的内容:

 #include #include int main(){ struct xx{ int x; struct yy{ char s; struct xx *p; } *q; /*Here is the change to your example. You cannot have a structur without a declactor inside of another structur! Your version might due to compiler extensions still work*/ }; struct xx test; test.q = (struct yy*)malloc(sizeof(struct yy)); test.q->s = 'a'; test.q->p = (struct xx*)malloc(sizeof(struct xx)); test.q->p->x = 1; test.q->p->q = (struct yy*)malloc(sizeof(struct yy)); test.q->p->q->s = 'b'; printf("s: %c\n", test.q->s); printf("x: %d\n", test.q->p->x); printf("s: %c\n", test.q->p->q->s); return 0; } 

我用gcc和以下选项编译它:

 gcc -ansi -pedantic -Wall -W -Wshadow -Wcast-qual -Wwrite-strings test.c -o 

两种变体都具有相同的输出

 s: ax: 1 s: b 

现在,如果你想在c ++中做同样的事情,你的结构不必改变,但要使用内部结构,你必须调用范围解析运算符(::)如下:

 test.q = (xx::yy*)malloc(sizeof(xx::yy)); test.q->s = 'a'; test.q->p = (xx*)malloc(sizeof(xx)); test.q->p->x = 1; test.q->p->q = (xx::yy*)malloc(sizeof(xx::yy)); test.q->p->q->s = 'b'; printf("s: %c\n", test.q->s); printf("x: %d\n", test.q->p->x); printf("s: %c\n", test.q->p->q->s); 

C不允许您在函数定义中嵌套类型声明。 另外,要消除关于“不声明任何内容的警告,您应该合并struct yy和member q类型的声明。以下编译带有最大警告的gcc

 struct xx { int x; struct yy { char s; struct xx *p; } *q; }; int main() { return 0; } 

好吧,cstdio需要被称为stdio.h。 至于结构,在C ++中不需要struct-keyword。

你没有真正定义结构成员,而是指针成员,所以看起来它应该适用于任何一种情况似乎都是合理的。

我只是稍加修改和gcc编译器测试它

 struct xx { int x; struct yy { char s; struct xx *p; }; struct yy *q; }; int main() { return 0; } 

用gcc编译

 $ gcc test.c test.c:3: warning: declaration does not declare anything 

我编译但发出警告。 由于我的C太生锈,不能再说了。

基于我的简短研究和Otto发布的错误消息,似乎C不允许结构是通用命名空间容器,如C ++类和结构(当然,因为C甚至不支持类)。 所以你不能在C中嵌套结构定义。你必须在外部结构声明之外声明内部结构,如下所示:

 struct yy { char s; struct xx *p; }; struct xx { int x; struct yy *q; }; 

我看到这些结构相互交叉引用。 因此,如果在C中甚至可以实现,则可能必须使用如下行来预先声明后面的结构:

 struct xx; 

(高于其他两个声明)。