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

标签 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;
}

这是故意的还是什么?

环境:

  • 海湾合作委员会 (Ubuntu 4.8.2-19ubuntu1) 4.8.2
  • Ubuntu clang 版本 3.5-1ubuntu1(主干)(基于 LLVM 3.5)

命令:

  • gcc 测试.c
  • clang 测试.c

最佳答案

简短回答: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 Declarations

Syntax

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

一切都在于initializer的定义,可以在6.7.8中找到:

6.7.8 Initialization

Syntax

1

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

12 The rest of this subclause deals with initializers for objects that have aggregate or union type.

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.

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

关于clang 和 gcc 具有复合文字的不同行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27734247/

相关文章:

c - gcc 静态库链接与动态链接

c - clang 中的静态预计算优化

c++ - clang 中明确指定的参数无效,但在 gcc 中编译成功——谁错了?

c - 如何获取陷入无限循环的 C 程序的代码覆盖率信息?

c - 在 gcc 中编译时出现警告有何影响?可能会产生什么后果?

c - 提取交错 float 据

c - 如何删除指针数组的第一个值?

c++ - 为什么 clang 并不总是为相同的静态 constexpr 产生恒定值

c++ - 指向 C++ 类的不透明 C 指针的正确 typedef 是什么?

c++ - GCC/g++ cout << 与 printf()