为什么这个带有字符数组的代码(被赋予一个变量作为大小)进行编译?

Why does this code with a character array, which was given a variable as size, compile?

本文关键字:变量 一个 编译 字符 数组 为什么 代码      更新时间:2023-10-16

玩模板时,我遇到了一个有趣的现象,即数组和定义它的大小,我认为这在C++是不允许的。

我使用了一个全局变量来定义 main() 中数组的大小,并且由于某种原因它起作用(请参阅下面的代码)

1)为什么这甚至编译?我认为只有 constexpr 可用于数组大小

2)假设上述是有效的,它仍然没有解释为什么即使sz = 8明显小于字符串的大小,它仍然有效

3)为什么我们会得到那个奇怪的"@"和"?"。我尝试了不同的字符串组合,例如,只有数字字符("123456789")并且没有出现。

感谢任何帮助。谢谢。

这是我的代码

#include <iostream>
#include <cstring>

using namespace std;

int sz = 8;
int main()
{
const char temp[sz] = "123456abc"; //9 characters + 1 null?
cout << temp << endl;
return 0;
}

输出:

123456AB @

1)为什么这甚至编译?我认为只有 constexpr 可用于数组大小

提问者是正确的,可变长度数组 (VLA) 不是标准C++。g++ 编译器通过扩展包括对 VLA 的支持。这怎么可能?编译器开发人员几乎可以添加任何它想要的东西,只要满足标准要求的行为。由开发人员记录行为。

2)假设上述是有效的,它仍然没有解释为什么即使sz = 8明显小于字符串的大小,它仍然有效

通常,如果使用超过数组大小的值初始化数组,g++ 会发出错误。在这种情况下,我必须通过文档进行确认,以查看C++标准是否需要错误。这似乎是出错的好地方,但我不记得是否需要错误。

在这种情况下,VLA 扩展似乎有一个副作用,可以消除 g++ 通常因尝试过度填充数组而吐出的错误。这很有意义,因为编译器在编译时不知道数组的大小,在一般情况下,无法执行测试。没有测试,没有错误。

C++标准不涵盖这些内容,因为不支持 VLA。

快速浏览一下允许VLA的C标准,并没有为这种情况找到任何指导。C 初始化 VLA 的规则非常简单:你不能。编译器不知道编译时数组的大小,因此无法初始化。字符串文字可能有例外,但我还没有找到。

我也没有在 GCC 文档中找到对行为的良好描述。

clang 根据我对 C 标准的阅读产生了我预期的错误:错误:可变大小的对象可能无法初始化

附录:可能应该先检查堆栈溢出并节省大量时间:初始化可变长度数组。

3)为什么我们会得到那个奇怪的"@"和"?"。我尝试了不同的字符串组合,例如,只有数字字符("123456789")并且没有出现。

似乎正在发生的事情,由于这些都不是标准的,我没有引号来支持它,字符串文字被复制到 VLA 中,最大为 VLA 的大小。VLA 末尾之后的文本部分将被静默丢弃。这包括空终止符,并且在打印未终止的char数组时未定义行为。

溶液:

尽可能坚持标准化行为。主要编译器可以选择警告您非标准代码。使用 gcc 选项将-pedantic与编译器一起使用,/permissive-与最新版本的 Visual Studio 一起使用。当被迫跳出标准时,请查阅编译器文档或实现者本身以获取粘性或未记录的位。

如果你没有得到好的答案,试着找到另一条路。

相关文章: