clang和gcc与复合文字的不同行为

时间:2015-01-01 20:12:37

标签: c gcc clang c99 compound-literals

最近遇到过复合文字,据我了解,以下是使用它的正确方法。幸运的是,它适用于ubuntu上的gcc和clang。

int main() {
  int *p = (int []) {1, 2};
  return 0;
}

但是,我注意到使用复合文字的另一种方法,如下所示。感觉有点奇怪;这只是数组初始化器。以下代码使用clang编译良好,但使用gcc array initialized from non-constant array expression失败。

int main() {
  int p[] = (int []) {1, 2};
  return 0;
}

这是故意还是什么?

ENV:

  • gcc(Ubuntu 4.8.2-19ubuntu1)4.8.2
  • Ubuntu clang版本3.5-1ubuntu1(主干)(基于LLVM 3.5)

CMD:

  • gcc test.c
  • clang test.c

2 个答案:

答案 0 :(得分:6)

简短回答:Clang承认该程序使用了扩展名

接受你所写的内容int p[] = (int []) {1, 2};,是一个Clang扩展。 GCC被允许拒绝它,因为它不是C99的一部分(C99 standard引入的复合文字,可以用作参考)。

事实上,我的Clang版本可以在你的程序上发出警告。有趣的是,它将您的行称为“GNU扩展”:

~ $ clang -std=c99 -pedantic t.c
t.c:2:7: warning: initialization of an array of type 'int []' from a compound
      literal of type 'int [2]' is a GNU extension
      [-Wgnu-compound-literal-initializer]
  int p[] = (int []) {1, 2};
      ^     ~~~~~~~~~~~~~~~
1 warning generated.
~ $ clang -v
Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
Target: x86_64-apple-darwin13.4.0
Thread model: posix

答案很长

int p[] = (int []) {1, 2};行是一个声明。它应该遵循第6.7节中给出的语法:

  

6.7声明

     

语法

     

1

declaration:
    declaration-specifiers init-declarator-listopt ;

declaration-specifiers:
    storage-class-specifier declaration-specifiersopt
    type-specifier declaration-specifiersopt
    type-qualifier declaration-specifiersopt
    function-specifier declaration-specifiersopt

init-declarator-list:
    init-declarator
    init-declarator-list , init-declarator

init-declarator:
    declarator
    declarator = initializer

所有这些都取决于初始化程序的定义,可以在6.7.8中找到:

  

6.7.8初始化

     

<强>语法

     

1

initializer:
    assignment-expression
    { initializer-list }
    { initializer-list , }
…
     

...

     

12本子条款的其余部分涉及具有聚合或联合类型的对象的初始值设定项。

     

...

     

16否则,具有聚合或联合类型的对象的初始值设定项应为括号内的元素或命名成员的初始值设定项列表

6.7.8:16的重点是我的。基本上,这是您的程序不满足的C99标准的一部分。

答案 1 :(得分:-1)

复合文字在C99和C ++中有不同的行为。

在C ++中,它只有一个表达式存储持续时间,而不是自动持续时间。如果这是在C ++模式下编译的,那么它将无法工作,因为复合文字对象在表达式完成后消失。

这可以解释@ cremno关于静态存储持续时间和自动存储持续时间的描述。