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

so6*_*1pi 12 c gcc

以下代码为两者打印出相同的地址ab使用GCC(未与其他编译器一起测试):

#include <stdio.h>

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

int main() {
    show();
}
Run Code Online (Sandbox Code Playgroud)

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

Ant*_*ala 21

C11 6.7.6.2p1段说:

约束

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

当你的程序违反了不得(0为不大于零),该计划将有不确定的行为,但在这种情况下出现的限制范围内部分.正如第4一致性所说

4一致性

  1. 在本国际标准中,"应"应被解释为对实施或计划的要求; 相反,"不得"应被解释为禁令.

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

另外,5.1.1.3p1说:

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

用脚注说:

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


从而

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

  • 这种数组的存在是违反约束的

  • 但是,GCC允许零大小的数组作为扩展

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

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

  • 海湾合作委员会的文件说:

    [...]要获得标准所需的所有诊断,您还应指定-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];
    
    Run Code Online (Sandbox Code Playgroud)
  • 但是,GCC仍会编译您的程序,即使它是一个不正确的程序(除非您使用-pedantic-errors); 在这种情况下,自然不会适用该标准的任何要求.

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


msc*_*msc 5

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

如果你-pedantic使用gcc选项编译它.它会发出警告,说:

zero.c:3:6:警告:ISO C禁止零大小数组'a'[ - >迂腐]