我正在做一个练习,在这个练习中,我必须证明C和C++常量表达式之间的区别.用C++编写类似这样的代码是有效的:

const int size_1 = 2;
const int size_2 = 2;

const int arr[size_1 + size_2] = { 1, 2, 3, 4 };

int main() {
  return arr[0];
}

但我预计,当复制到.c文件并用C编译时,它会抛出错误-事实上,我已经使用在线编译器判断过它,它返回:

main.c:6:11: error: variably modified ‘arr’ at file scope

我相信这就是我要找的.

但是,当我用机器上的命令gcc main.c编译完全相同的代码时,代码编译时没有错误,并且返回值是正确的.有人能解释一下我的错误在哪里吗?

我的编译器版本:

Apple clang version 15.0.0 (clang-1500.0.40.1)
Target: arm64-apple-darwin23.0.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

推荐答案

…代码编译时不会出现错误…

(A)C标准不要求编译器发出诊断消息或拒绝使用C标准未定义的常量形式的程序(或通常拒绝具有未定义行为的程序).该标准要求程序对违反语法规则和明确列为约束的规则发出诊断消息(根据C 2018 5.1.1.3 1),但在表达式中使用const个变量表示数组大小不属于此类违规.对于标准中其他违反"要求"的情况,标准没有定义必须发生什么(C 2018 4 2),实现可以接受这样的程序(C 2018 4 6).

(B)C标准明确允许实现接受其他形式的常量表达式(C 2018 6.6 10,"实现可以接受其他形式的常量表达式").

(C)Testing with Clang 15.0.0 for ARMv8 on Compiler Explorer生成消息"可变长度数组折叠为常量数组作为扩展[-WGNU-Folding-Constant]",即使使用默认的编译器选项也是如此.我没有苹果版本的Clang 15.0.0可以测试,所以,如果你没有看到这条消息,这似乎是苹果版本的不同之处.添加switch -std=c18 -pedantic-errors可能会导致编译器拒绝该代码.

C++相关问答推荐

为什么listen()(在调用accept()之前)足以让应用程序完成3次握手?

strftime函数中%s的历史意义是什么?为什么没有记录?

C语言中字符数组声明中的标准

如何在C宏中确定 struct 中元素的类型?

如何跨平台处理UTF-16字符串?

拥有3x3二维数组并访问数组[1][3]等同于数组[2][0]?

CSAPP微型shell 实验室:卡在sigprocmask

我怎么才能用GCC编译一个c库,让它包含另一个库呢?

获取每个循环迭代结束时的当前时间

OpenSSL:如何将吊销列表与SSL_CTX_LOAD_VERIFY_LOCATIONS一起使用?

获取前2个连续1比特的索引的有效方法

当内存来自Malloc时,将char*转换为另一个指针类型是否违反了严格的别名规则?

理解bzip2的BZ2_解压缩函数中的状态重新分配

Fscanf打印除退出C代码为1的程序外的所有内容

当用C打印过多的';\n';时输出不正确

生成一个半RNG,结果用C表示(无随机/随机)

无法将字符串文字分配给 C 中的字符数组

为什么INT_MIN是在c语言的头文件limits.h中定义的(-INT_MAX-1)而不是直接使用-2147483648

C 中从 Unix 纪元时间转换的损坏

计算 e^x 很好.但不是 x 的罪