Nested structures

前端 未结 6 1992
旧时难觅i
旧时难觅i 2020-12-03 08:42

The following code compiles on a C++ compiler.

#include 
int main()
{
    struct xx
    {
        int x;
        struct yy
        {
                    


        
相关标签:
6条回答
  • 2020-12-03 08:54

    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;
    }
    
    0 讨论(0)
  • 2020-12-03 08:58

    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).

    0 讨论(0)
  • 2020-12-03 09:02

    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.

    0 讨论(0)
  • 2020-12-03 09:13

    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.

    0 讨论(0)
  • 2020-12-03 09:20

    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);
    
    0 讨论(0)
  • 2020-12-03 09:21

    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.

    0 讨论(0)
提交回复
热议问题