Nested structures
The following code compiles on a C++ compiler.
#include <cstdio>
int main()
{
stru开发者_开发百科ct xx
{
int x;
struct yy
{
char s;
struct xx *p;
};
struct yy *q;
};
}
Would there be any difference in behavior while compiling with a C compiler?
i.e. would there be any compiler error?The code in your post is obviously incomplete, just declarations, so it is hard to say anything conclusive.
On obvious difference is that in C++ the inner struct type will be a member of outer struct type, while in C language both struct types will be members of the same (enclosing) scope. (BTW, was it your intent to declare them locally in main
?).
In other words, in C++ the code that follows would have to refer to the structs as xx
and xx::yy
, while in C they would be just xx
and yy
. This means that the further code would look different for C and C++ and if it will compile in C++, it wouldn't compile in C and vice versa.
Added: C language prohibits declaring struct types inside other structs without declaring a member of that type. So, you struct yy
declaration is illegal in C and will produce compiler diagnostic message. If you wanted your code to become legal in both C and C++, you'd have to combine the struct yy
declaration with some data member declaration. In your case that could be pointer q
:
struct xx {
int x;
struct yy {
char s;
struct xx *p;
} *q;
};
The above is legal in both C and C++ (taking into account the differences I explained earlier), but your original declaration is not legal in C.
Here are some changes (thanks to AndreyT):
Obviously you have to change the headers to make this compile. But even then, this seems not to be standard C as AndreyT pointed out. Nonetheless will some compilers like gcc still compile it as expected and only issue a warning. Likewise, Microsoft doesn't seem to interpret the standard too strictly:
"Structure declarations can also be specified without a declarator when they are members of another structure or union"
To make it standard C you have to turn your "struct yy" declaration into a definition. Then your code will be valid in C and in C++. To illustrate what is going on, I rewrote it in a, in my opinion, more comprehensible fashion and added a little test on what is going on.
#include<stdio.h>
#include<stdlib.h>
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;
}
You can easily see, that you have a struct yy with a pointer to xx and the struct xx has a pointer to yy. This is equivalent to which can be written as followed in ansi-C:
#include<stdio.h>
#include<stdlib.h>
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;
}
I compiled it with gcc and the following options:
gcc -ansi -pedantic -Wall -W -Wshadow -Wcast-qual -Wwrite-strings test.c -o
Both variants will have the same output
s: a
x: 1
s: b
Now if you want to do the same in c++, your struct doesn't have to change but to use the inner struct you have to call the scope resolution operator (::) as follow:
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 does not permit you to nest a type declaration inside a function definition. Also, to eliminate the warning about "does not declare anything, you should merge the declarations of type struct yy
and member q
. The following compiles with gcc
with max warnings on:
struct xx
{
int x;
struct yy
{
char s;
struct xx *p;
} *q;
};
int main()
{
return 0;
}
Well, cstdio needs to be referred as stdio.h. As for the structure, the struct-keyword is not required in C++.
You don't really define struct members, but pointer members, so it seems plausible that it should work in either case.
I just tested it with slight modifications and the gcc compiler
struct xx {
int x;
struct yy { char s; struct xx *p; };
struct yy *q;
};
int main() { return 0; }
Compile with gcc
$ gcc test.c
test.c:3: warning: declaration does not declare anything
I compiles but gives a warning. Since my C is too rusty can't say any more.
Based on my brief research and the error message posted by Otto, it appears that C doesn't allow structures to be general-purpose namespace containers like C++ classes and structures are (naturally, because C doesn't even support classes). So you can't nest structure definitions in C. You would have to declare the inner structure outside of the outer structure declaration like this:
struct yy
{
char s;
struct xx *p;
};
struct xx
{
int x;
struct yy *q;
};
I see that the structures cross-reference each other. So if this is even possible in C, you may have to pre-declare the later structure with a line like:
struct xx;
(above both other declarations).
精彩评论