5

I saw this way to implement some kind of struct inheritance with anonymous struct in C11, and wanted to try it out. Here is what I have:

struct struct_a {
    int aa;
};

struct struct_b {
    struct struct_a;
    int bb;
};

int main(void)
{
    volatile struct struct_b my_b;
    my_b.aa = 5; /* not a member of my_b */
    my_b.bb = 6;

}

Result from gcc:

$ gcc -std=c11 struct_extend.c 
struct_extend.c:11:20: warning: declaration does not declare anything
     struct struct_a;
                    ^
struct_extend.c: In function ‘main’:
struct_extend.c:18:9: error: ‘volatile struct struct_b’ has no member named ‘aa’
     my_b.aa = 5; /* not a member of my_b */

Relevant:

$ gcc --version
gcc (Debian 6.3.0-18) 6.3.0 20170516

Is this not implemented in my compiler, or am I doing it wrong?

Gauthier
  • 40,309
  • 11
  • 63
  • 97
  • 1
    Possible duplicate of [What are anonymous structs and unions useful for in C11?](https://stackoverflow.com/questions/8932707/what-are-anonymous-structs-and-unions-useful-for-in-c11) – Tom Karzes Oct 17 '17 at 07:18
  • You need something after `struct struct_a;` in `struct struct_b` declaration. – David C. Rankin Oct 17 '17 at 07:19
  • [also related](https://stackoverflow.com/a/44524573/2371524) .. bottom line: to be sure your code is conforming without doubt, you have to use a quite verbose form, unfortunately. –  Oct 17 '17 at 08:29
  • If you use `gcc -std=c++11` it supports real inheritance... – Bo Persson Oct 17 '17 at 12:30

3 Answers3

5

According to GCC reference : use -fms-extensions flag, Which will enable the this feature.

  • Unless -fms-extensions is used, the unnamed field must be a structure or union definition without a tag (for example, ‘struct { int a; };’). If -fms-extensions is used, the field may also be a definition with a tag such as ‘struct foo { int a; };’, a reference to a previously defined structure or union such as ‘struct foo;’, or a reference to a typedef name for a previously defined structure or union type.

  • The option -fplan9-extensions enables -fms-extensions as well as two other extensions. First, a pointer to a structure is automatically converted to a pointer to an anonymous field for assignments and function calls.

I have used following command on GCC, it's working fine.

gcc -std=c11 -O2 -Wall -fms-extensions -pedantic -pthread ls.c
msc
  • 33,420
  • 29
  • 119
  • 214
4

The standard only allows structure and unions without a tag as unnamed members:

6.7.2.1 Structure and union specifiers - Paragraph 13

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.

Yours clearly has a tag, so it's not valid C. What the answer you linked to did is not any better either. The way to do it in a standard compliant way, is sadly quite verbose:

struct struct_b {
    union {
        struct struct_a _aa;
        struct { int aa; };
    };
    int bb;
};

Which really isn't anything to be impressed by. One can perhaps use a macro to avoid repeating the member declarations, but it's a code smell by now.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
  • That version of the code will fail under "modern" interpretations of the aliasing rules if anything tries to take the address of `_aa` and access the structure using the resulting pointer. – supercat Oct 17 '17 at 23:08
1

It appears you are attempting to make an anonymous unnamed struct containing int aa in struct_b, similar to the following:

#include <stdio.h>

struct struct_b {
    struct {
        int aa;
    };
    int bb;
};

int main(void)
{
    volatile struct struct_b my_b;
    my_b.aa = 5; /* now a member of my_b */
    my_b.bb = 6;

    printf ("my_b.aa: %d\nmy_b.bb: %d\n", my_b.aa, my_b.bb);

    return 0;
}

Example Use/Output

$ ./bin/strc2
my_b.aa: 5
my_b.bb: 6

This follows directly from the standard section cited by StoryTeller.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
  • I see. What would be the point of grouping the members of the inside struct, if it needs to be explicitly defined there anyway? – Gauthier Oct 17 '17 at 09:02
  • That's the $100 question. I've toyed with it a bit, adding multiple levels and multiple types, and I don't see any benefit to embedding an unnamed anonymous struct within a struct. Seems to me just declaring the variables within the original struct itself makes much more sense. I'd have to see the standards committee minutes where this was argued over, but I suspect that this was intended to provided the anonymous unnamed `struct` within a `union` for `bitfield` purposes and the fact you can do it with a struct is just a side-effect of unions and structs being handled the same way. – David C. Rankin Oct 17 '17 at 21:04
  • @DavidC.Rankin: The Standard is IMHO pretty horrible there, especially given "modern" aliasing rules which assume that an untagged structure that appears within a union won't alias a tagged structure with the same members. – supercat Oct 17 '17 at 23:13