为什么编译没有警告/错误?

时间:2015-03-16 10:59:48

标签: c gcc assembly x86

#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   $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

输出:

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

2 个答案:

答案 0 :(得分:3)

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

使用Gcc 4.1.2,它没有被检测到。来自docs [emph。矿]:

  

您绝不能创建导致模糊字段定义的结构。例如,这个结构:

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

a引用foo.a是不明确的。不支持此类构造,必须避免使用。 将来,可能会检测到此类构造并将其视为编译错误

版本4.6.4的强调条目已更改。

答案 1 :(得分:2)

它无法编译。

使用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版本。在C11中添加了匿名结构/联合(但在此之前作为gcc扩展存在)。