0x90
0x90

Reputation: 40982

Why does the compilation pass with no warnings/errors?

#include <stdio.h>
union {
    struct {
        int a;
        int c;
    };
    struct {
        int b;
        int a;
    };
}unionTry;

int main(){
    unionTry.a = 1;
    unionTry.b = 2;
    unionTry.c = 3;


    printf("a = 0x%x b = 0x%x c = 0x%x\n", unionTry.a, unionTry.b, unionTry.c); 
    return 0;
}

The disassembly:

  400578:   55                      push   %rbp
  400579:   48 89 e5                mov    %rsp,%rbp
  40057c:   c7 05 56 04 20 00 01    movl   $0x1,0x200456(%rip)        # 6009dc <unionTry>
  400583:   00 00 00 
  400586:   c7 05 50 04 20 00 02    movl   $0x2,0x200450(%rip)        # 6009e0 <unionTry+0x4>
  40058d:   00 00 00 
  400590:   c7 05 46 04 20 00 03    movl   $0x3,0x200446(%rip)        # 6009e0 <unionTry+0x4>
  400597:   00 00 00 
  40059a:   8b 0d 40 04 20 00       mov    0x200440(%rip),%ecx        # 6009e0 <unionTry+0x4>
  4005a0:   8b 15 3a 04 20 00       mov    0x20043a(%rip),%edx        # 6009e0 <unionTry+0x4>
  4005a6:   8b 35 30 04 20 00       mov    0x200430(%rip),%esi        # 6009dc <unionTry>
  4005ac:   bf bc 06 40 00          mov    $0x4006bc,%edi
  4005b1:   b8 00 00 00 00          mov    $0x0,%eax
  4005b6:   e8 e5 fe ff ff          callq  4004a0 <printf@plt>
  4005bb:   b8 00 00 00 00          mov    $0x0,%eax
  4005c0:   c9                      leaveq 
  4005c1:   c3                      retq   
  4005c2:   90                      nop

The output:

$gcc -Wall a.c && ./a.out
a = 0x2 b = 0x2 c = 0x3

Apparently it is a lack of C11 standard support. Is the following code is well defined:

union {
    struct {
        int a;
        int c;
    };
    struct {
        int a;
        int b;
    };
}unionTry;

Upvotes: 4

Views: 96

Answers (2)

mafso
mafso

Reputation: 5543

Anonymous structures and unions have been standardized in C11. Gcc allowed them before as an extension. For both versions, the structure or union declaration must be unambiguous (a in this code example is ambiguous and thus violates this rule). In C11, such violations must be detected at compile time, and new versions of Gcc follow this requirement also when compiling with a GNU dialect.

With Gcc 4.1.2, it isn't detected. From the docs [emph. mine]:

You must never create such structures that cause ambiguous field definitions. For example, this structure:

struct {
    int a;
    struct {
        int a;
    };
} foo;

It is ambiguous which a is being referred to with foo.a. Such constructs are not supported and must be avoided. In the future, such constructs may be detected and treated as compilation errors.

The emphasized entry has been changed for version 4.6.4.

Upvotes: 3

Lundin
Lundin

Reputation: 213872

It does not compile.

With MinGW, gcc 4.9.1 and your compiler settings:

gcc -Wall test.c
test.c:9:13: error: duplicate member 'a'
         int a;
             ^

With proper compiler settings:

gcc test.c -std=c11 -pedantic-errors -Wall -Wextra
test.c:9:13: error: duplicate member 'a'
         int a;
             ^

Update your version of gcc. Anonymous struct/union was added in C11 (but existed as a gcc extension before that).

Upvotes: 2

Related Questions