多个0长度数组具有相同的地址?

时间:2017-03-19 05:43:14

标签: c gcc

以下代码使用GCC打印出ab的相同地址(未经其他编译器测试):

#include <stdio.h>

void show() {
    {
        static char a[0];
        printf("%p\n", a);
    }
    {
        static char b[0];
        printf("%p\n", b);
    }
}

int main() {
    show();
}

我的问题是C标准是否允许多个变量具有相同的地址,或者这只是GCC的扩展?

4 个答案:

答案 0 :(得分:21)

C11 6.7.6.2p1段说:

  

<强>约束

     
      
  1. 除了可选的类型限定符和关键字static之外,[]可以分隔表达式或*。如果它们分隔表达式(指定数组的大小),则表达式应具有整数类型。如果表达式是常量表达式,它应具有大于零的值
  2.   

由于您的程序违反 (0不大于0),程序会有未定义的行为,但在这种情况下它会出现约束部分。正如4 Conformance部分所述

  

4符合性

     
      
  1. 在本国际标准中,“应”应被解释为实施或程序的要求;相反,''不应'被解释为禁止。

  2.   
  3. 如果违反约束或运行时约束之外的''shall''或''shall not''要求,则行为未定义。未定义的行为在本国际标准中以“未定义的行为”或“省略行为的任何明确定义”的方式表示。这三者之间的重点没有区别;他们都描述了“未定义的行为”。

  4.   

此外,5.1.1.3p1说:

  
      
  1. 如果预处理翻译单元或翻译单元包含违反任何语法,则符合要求的实施应至少生成一条诊断消息(以实现定义的方式标识)规则或约束,即使行为也明确指定为未定义或实现定义。在其他情况下不需要产生诊断消息。 [9])
  2.   

用脚注说:

  

9)意图是实施应确定每次违规的性质,并在可能的情况下进行本地化。当然,只要仍然正确地翻译了有效的程序,实现就可以自由地产生任意数量的诊断。 它也可能成功翻译无效的程序。

因此

  • C11没有大小为0的数组。

  • 此类数组的存在是约束违规

  • 但是,GCC允许zero-size arrays as an extension

  • 符合C的实施必须在此类使用时生成诊断消息。

  • 即使设置了-std=c11,GCC也会使用默认设置编译此默认设置而不输出诊断消息,这会使gcc -std=c11成为不合规的实现。

  • GCC documentation says that

      

    [...]要获得标准所要求的所有诊断,您还应指定-pedantic(或-pedantic-errors,如果您希望它们是错误而不是警告)。

  • 因此,要使用GCC以符合C11标准的方式进行编译,必须至少明确使用gcc -std=c11 -pedantic;然后你会得到:

    zerosizearray.c:5:21: warning: ISO C forbids zero-size array ‘a’ [-Wpedantic]
           static char a[0];
    
  • 但是,GCC仍会编译您的程序,即使它是不正确的程序(除非您使用-pedantic-errors);在这种情况下,自然不会适用标准的任何要求。

由于C标准实际上并不允许大小为零的对象(如果我正确读取,结构定义也必须至少有一个成员,依此类推),更重要的是,不同的对象必须占用不同的空间。对象的不同地址来自的内存;标准没有指定任何大小为0的对象的地址。

答案 1 :(得分:5)

在标准C中,不允许使用零大小的数组。

如果您使用gcc使用-pedantic选项进行编译。它会发出警告,说:

  

zero.c:3:6:警告:ISO C禁止零大小数组'a'[ - &gt; pedantic]

答案 2 :(得分:3)

正如其他人已经说过的那样,标准C&C中不允许使用0长度数组。 GCC编译器允许它作为扩展。我想补充一点:您发布的程序的行为是undefined。使用%p格式说明符时,必须强制转换为void*,因为printf的{​​{1}}格式说明符需要%p类型的参数。

请参阅此答案:printf and pointers

答案 3 :(得分:-2)

零长度数组是gcc扩展并且标准库不支持,行为取决于gcc扩展的实现

你可以在这里看到GCC文档

6.17 Arrays of Length Zero

(?<=cn=)(?!.*cn=)([^\\]+) 被称为a zero length array

  • 灵活数组成员写为内容[],不带0。
  • 灵活数组成员的类型不完整,因此可能无法应用sizeof运算符。作为零长度数组原始实现的一个怪癖,sizeof的计算结果为零。
  • 灵活数组成员可能只显示为非空的结构的最后一个成员。
  • 包含柔性阵列成员的结构或包含这种结构的联合(可能是递归地),可以不是结构的成员或阵列的元素。 (但是,GCC允许这些用途作为扩展。)