简体   繁体   English

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

[英]clang and gcc different behavior with compound literal

Came across compound literal recently, and as far as I understand it, the following is the correct way of using it. 最近遇到了复合文字,据我所知,以下是使用它的正确方法。 Fortunately, it works both with gcc and clang on ubuntu. 幸运的是,它适用于ubuntu上的gcc和clang。

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

However, I notice another way of using compound literal, shown below. 但是,我注意到使用复合文字的另一种方法,如下所示。 It feels a bit weird; 感觉有点奇怪; this is just array initializer. 这只是数组初始化器。 The following code compiles fine with clang, but failed with gcc, array initialized from non-constant array expression . 下面的代码使用clang编译好,但是使用gcc, array initialized from non-constant array expression失败。

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

Is this intentional or what? 这是故意还是什么?

ENV: ENV:

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

CMD: CMD:

  • gcc test.c gcc test.c
  • clang test.c clang test.c

Short answer: Clang confesses that the program uses an extension 简短回答:Clang承认该程序使用了扩展名

Accepting what you wrote, int p[] = (int []) {1, 2}; 接受你写的内容, int p[] = (int []) {1, 2}; , is a Clang extension. ,是一个Clang扩展。 GCC is allowed to reject it, because it is not part of C99 (the C99 standard introduced compound literals and can be used as reference). GCC被允许拒绝它,因为它不是C99的一部分( C99标准引入了复合文字,可以作为参考)。

In fact, my version of Clang can be made to emit a warning on your program. 事实上,我的Clang版本可以在你的程序上发出警告。 It is funny that it calls your line a “GNU extension”: 有趣的是,它将您的行称为“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

Long answer 答案很长

The line int p[] = (int []) {1, 2}; int p[] = (int []) {1, 2}; is a declaration. 是宣言。 It should follow the syntax given in clause 6.7: 它应该遵循第6.7节中给出的语法:

6.7 Declarations 6.7声明

Syntax 句法

1 1

 declaration: 宣言:\n    declaration-specifiers init-declarator-list opt ; declaration-specifiers init-declarator-list opt ;\n\ndeclaration-specifiers: 声明-符:\n    storage-class-specifier declaration-specifiers opt 存储类说明符声明,符选择\n    type-specifier declaration-specifiers opt type-specifier declaration-specifiers opt\n    type-qualifier declaration-specifiers opt type-qualifier声明 - 说明符opt\n    function-specifier declaration-specifiers opt function-specifier declaration-specifiers opt\n\ninit-declarator-list: 初始化声明符列表:\n    init-declarator 初始化声明符\n    init-declarator-list , init-declarator init-declarator-list,init-declarator\n\ninit-declarator: 初始化声明符:\n    declarator 声明符\n    declarator = initializer declarator =初始化器 

All lies on the definition of initializer , which can be found in 6.7.8: 所有这些都取决于初始化程序的定义,可以在6.7.8中找到:

6.7.8 Initialization 6.7.8初始化

Syntax 句法

1 1

 initializer: 初始化:\n    assignment-expression 赋值表达式\n    { initializer-list } {initializer-list}\n    { initializer-list , } {initializer-list,}\n ... 

...

12 The rest of this subclause deals with initializers for objects that have aggregate or union type. 12本子条款的其余部分涉及具有聚合或联合类型的对象的初始值设定项。

...

16 Otherwise, the initializer for an object that has aggregate or union type shall be a brace-enclosed list of initializers for the elements or named members . 16否则,具有聚合或联合类型的对象的初始值设定项应该是元素或命名成员的大括号括起来的初始值设定项列表

The emphasis in 6.7.8:16 is mine. 6.7.8:16的重点是我的。 Basically, this is the part of the C99 standard that your program does not satisfy. 基本上,这是您的程序不满足的C99标准的一部分。

Compound literal has different behavior in C99 and C++. 复合文字在C99和C ++中具有不同的行为。

In C++ it has only a single expression storage duration, not automatic duration. 在C ++中,它只有一个表达式存储持续时间,而不是自动持续时间。 If this is compiled in C++ mode, then it won't work, because the compound literal object disappears after the expression finishes. 如果这是在C ++模式下编译的,那么它将无法工作,因为复合文字对象在表达式完成后消失。

This might explain @cremno's description on static vs automatic storage duration. 这可能解释了@ cremno关于静态存储持续时间和自动存储持续时间的描述。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM