Clang在C89模式下无法在非常量数组初始化器上抛出错误

12 c clang c89

这是Clang的一个错误吗?以下代码:

#include <stdio.h>

int main(void)
{
    int foo = 42;
    int bar[1] = { foo };
    printf("%d\n", bar[0]);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译精细使用:

clang -Wall -Wextra -Werror -pedantic -pedantic-errors -std=c89 -o foo foo.c
Run Code Online (Sandbox Code Playgroud)

我不认为它应该编译,因为初始化列表bar[]包含一个表达式foo,它不是编译时常量.实际上,如果我使用gcc而不是clang,我会得到预期的结果:

$ gcc -Wall -Wextra -Werror -pedantic -pedantic-errors -std=c89 -o foo foo.c
foo.c: In function ‘main’:
foo.c:6: error: initializer element is not computable at load time
Run Code Online (Sandbox Code Playgroud)

这个问题及其接受的答案,以及C89描述的摘录表明GCC是对的,Clang是错误的:

静态对象或聚合或联合的初始值设定项中的表达式必须是常量表达式.

我的clang版本是:

$ clang -v
Apple LLVM version 4.2 (clang-425.0.28) (based on LLVM 3.2svn)
Target: x86_64-apple-darwin11.4.2
Run Code Online (Sandbox Code Playgroud)

我注意到的一件事是opensource.apple.com上的clang的最新版本,即clang 425.0.24,只比我的clang早了4个subminor修订版,它确实有对数组初始值设定项进行单元测试.但是,除非我遗漏了某些内容,否则不会测试具有非const表达式的块范围自动数组的初始化(仅测试块范围静态数组和全局数组).这是我找到的测试文件.

那么,这笔交易是什么?

Sha*_*our 5

这看起来像旧版本的clang版本中3.5的错误,为此代码提供了以下警告:

warning: initializer for aggregate is not a compile-time constant [-Wc99-extensions]
int bar[1] = { foo };
             ^~~~~~~
Run Code Online (Sandbox Code Playgroud)

和编译选项出错(请参见实时).

由于缺乏公共C89草案,我发现gcc有一个关于非常数初始化器的部分说:

与标准C++和ISO C99一样,自动变量的聚合初始值设定项的元素不需要是GNU C中的常量表达式.

这证实他们曾经被要求在C99之前成为常数表达式.

标签告诉我们,C89标准的相关引用来自sectioon 3.5.7并说:

具有静态存储持续时间的对象的初始值设定项中的所有表达式或具有聚合或联合类型的对象的初始化列表中的所有表达式都应为常量表达式.

  • 这是相关位(§3.5.7约束):"具有静态存储持续时间的对象的初始值设定项中的所有表达式或具有聚合或联合类型的对象的初始化列表中的所有表达式都应为常量表达式." (3认同)