【问题标题】:Why does the compilation pass with no warnings/errors?为什么编译通过而没有警告/错误?
【发布时间】:2015-03-16 10:59:48
【问题描述】:
#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;

【问题讨论】:

  • 如果编译,不错的 q,+1。期待答案。也许编译器对未命名的结构进行优化,让我们看看。
  • 不为我编译。这是哪个 Gcc 版本?
  • @mafso 我的虚拟机上确实有相当旧的编译器版本:&gt;gcc --version gcc (GCC) 4.1.2 Copyright (C) 2006 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 你得到什么错误?
  • @mafso, here 它的行为或其他编译器版本的意外行为
  • @0x90 我想匿名结构/联合尚未添加到旧版本的 gcc 中。 2012年正式加入C语言,采用C11标准。

标签: c gcc assembly x86


【解决方案1】:

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

使用 Gcc 4.1.2,它不会被检测到。来自docs [emph.我的]:

您绝不能创建导致字段定义不明确的结构。比如这个结构:

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

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

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

【讨论】:

    【解决方案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 扩展存在)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-20
      相关资源
      最近更新 更多