【问题标题】:clang and gcc different behavior with compound literalclang 和 gcc 使用复合文字的不同行为
【发布时间】:2015-01-01 20:12:37
【问题描述】:

最近遇到复合文字,据我了解,以下是正确的使用方法。幸运的是,它适用于 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;
}

这是故意的还是什么?

环境:

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

CMD:

  • gcc test.c
  • clang test.c

【问题讨论】:

  • 编译它们的命令行是什么?
  • @jww 已编辑添加用于构建的 cmd。

标签: c gcc clang c99 compound-literals


【解决方案1】:

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

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

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

~ $ clang -std=c99 -pedantic t.c t.c:2:7:警告:从复合中初始化“int []”类型的数组 'int [2]' 类型的文字是 GNU 扩展 [-Wgnu-compound-literal-initializer] int p[] = (int []) {1, 2}; ^ ~~~~~~~~~~~~~~~ 生成 1 个警告。 ~ $ 铿锵 -v Apple LLVM 5.1 版(clang-503.0.40)(基于 LLVM 3.4svn) 目标:x86_64-apple-darwin13.4.0 线程模型:posix

长答案

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

6.7 声明

语法

1

声明:
    声明说明符 init-declarator-listopt ;

声明说明符:
    存储类说明符声明说明符opt
    类型说明符声明说明符opt
    类型限定符声明说明符opt
    函数说明符声明说明符opt

初始化声明器列表:
    初始化声明器
    初始化声明器列表,初始化声明器

初始化声明器:
    声明者
    声明器 = 初始化器

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

6.7.8 初始化

语法

1

初始化器:
    赋值表达式
    {初始化列表}
    {初始化列表,}
…

12 本小节的其余部分处理具有聚合或联合类型的对象的初始化程序。

16 否则,具有聚合或联合类型的对象的初始化程序应为元素或命名成员的初始化程序的大括号括起来的列表

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

【讨论】:

  • GCC 似乎只为具有静态存储持续时间的对象实现此功能 (static int p[] = (int []) {1, 2};)。但是 Clang 也为具有自动存储持续时间的人实现了它。奇怪的。当它在 Clang 中实现时可能是一个疏忽,因为 test/Sema/array-init.c 中的测试用例不包括这种情况。
【解决方案2】:

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

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

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

【讨论】:

  • 复合文字根本不是标准 C++ 的一部分。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-11
  • 2019-04-29
  • 1970-01-01
相关资源
最近更新 更多