为什么编译通过没有warnings/errors?

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;
}

反汇编:

  400578:   55                      push   %rbp
  400579:   48 89 e5                mov    %rsp,%rbp
  40057c:   c7 05 56 04 20 00 01    movl   [=12=]x1,0x200456(%rip)        # 6009dc <unionTry>
  400583:   00 00 00 
  400586:   c7 05 50 04 20 00 02    movl   [=12=]x2,0x200450(%rip)        # 6009e0 <unionTry+0x4>
  40058d:   00 00 00 
  400590:   c7 05 46 04 20 00 03    movl   [=12=]x3,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    [=12=]x4006bc,%edi
  4005b1:   b8 00 00 00 00          mov    [=12=]x0,%eax
  4005b6:   e8 e5 fe ff ff          callq  4004a0 <printf@plt>
  4005bb:   b8 00 00 00 00          mov    [=12=]x0,%eax
  4005c0:   c9                      leaveq 
  4005c1:   c3                      retq   
  4005c2:   90                      nop

输出:

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

显然是缺少C11标准支持。以下代码是否定义明确:

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

它不编译。

使用 MinGW、gcc 4.9.1 和您的编译器设置:

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

使用正确的编译器设置:

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

更新您的 gcc 版本。 Anonymous struct/union 是在 C11 中添加的(但在此之前作为 gcc 扩展存在)。

匿名结构和联合已在 C11 中标准化。 Gcc 之前允许它们作为扩展。对于这两个版本,结构或联合声明必须是明确的(此代码示例中的 a 是不明确的,因此违反了此​​规则)。在 C11 中,此类违规必须在编译时检测到,新版本的 Gcc 在使用 GNU 方言编译时也遵循此要求。

对于 Gcc 4.1.2,未检测到它。来自 docs [强调。我的]:

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.

强调的条目已针对版本 4.6.4 进行了更改。