Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C: How to access different types of anonymous or unnamed nested structs

I noticed that there are a few ways to define structs inside other structs in C:

struct s {
    int abc;

    struct {
        int a;
    };

    struct {
        int b;
    } intern;

    struct i {
        int c;
    };

    struct i2 {
        int d;
    } intern2;

    struct i3 {
        int e;
    };
    struct i3 intern3;
};

This struct compiles fine using gcc or g++, so I assume all parameters are accessible in some way. I tried it like this:

int main(int argc, char const *argv[])
{
    struct s mystruct;

    mystruct.abc = 0;
    mystruct.a = 1;
    mystruct.intern.b = 2;
    mystruct.c = 3; // <-- does not compile
    mystruct.intern2.d = 4;
    mystruct.intern3.e = 5;

    return 0;
}

Apart from the access mystruct.c, everything compiles (compile error message is ‘struct s’ has no member named ‘c’). Am I accessing the struct parameters in the correct way? Are there alternatives? How do I access the c parameter?

like image 585
PieterV Avatar asked Jul 19 '16 11:07

PieterV


2 Answers

In your code,

struct i {
        int c;
    };

there is no member variable of type struct i neither it qualifies for anonymous structure Note. If you create a variable of that type, you'll be able to access the member variable c, similar to what you've done for struct i3 with intern3 variable.

Adding a bit regarding the error message you're seeing,

struct s has no member named c

because, in case of an anonymous structure, the members are considered a direct member of the containing structure. In case of a struct definition with a tag, that structure is not an anonymous structure and the member of the structure needs a structure variable of that type to be accessed.


NOTE:

Regarding anonymous structure, quoting C11, chapter §6.7.2.1, (emphasis mine)

An unnamed member whose type specifier is a structure specifier with no tag is called an anonymous structure; an unnamed member whose type specifier is a union specifier with no tag is called an anonymous union. The members of an anonymous structure or union are considered to be members of the containing structure or union. This applies recursively if the containing structure or union is also anonymous.

like image 167
Sourav Ghosh Avatar answered Sep 21 '22 10:09

Sourav Ghosh


From the gcc docs:

As permitted by ISO C11 and for compatibility with other compilers, GCC allows you to define a structure or union that contains, as fields, structures and unions without names. For example:

 struct {
   int a;
   union {
     int b;
     float c;
   };
   int d;
 } foo;

In this example, you are able to access members of the unnamed union with code like ‘foo.b’.

You were able to get at mystruct.a because the structure had no tag. You can't get at your mystruct.c because the containing struct for c has the tag i.

Change:

 struct i {
        int c;
    };

to

struct {
    int c;
}

and you should be able to get at mystruct.c.

like image 28
evaitl Avatar answered Sep 21 '22 10:09

evaitl