为什么全局数组大小应该是整数常量?

8
在C++中,我尝试声明一个具有某个大小的全局数组。我得到了错误消息:'array bound is not an integer constant before ‘]’ token'。但是当我在main()函数中声明了一个相同类型的数组时,它可以正常工作。为什么这里会有不同的行为?
int y=5;
int arr[y];         //When I comment this line it works fine

int main()
{
    int x=5;
    int arr2[x];        // This line doesn't show any error.
}

编辑:许多人认为这个问题与获取错误“在'token'之前数组边界不是整数常量”重复。但是那个问题并没有回答为什么存在不同的行为。


3
即使在 main 函数中,使用可变长度数组扩展也是不合法的。 - Jarod42
4
所有 C++ 数组的边界都需要在编译期间确定一个值。如果将此类代码放入“主函数”中后,编译器“接受”了它,那么你正在使用编译器扩展功能,即使 VLAs(可变长度数组)不受 C++ 标准支持,也能进行编译。 - Algirdas Preidžius
2
请勿将“没有编译器错误”与“正常工作”混淆。在这种情况下,“正常工作”意味着您的代码依赖于非标准编译器提供的扩展,也就是说它还算可以,但不是可移植的C++。 - 463035818_is_not_a_number
为什么不将 yx 声明为 const?你需要修改 yx 的值吗?希望不需要,因为这会引发许多关于 arrarr2 大小的问题,特别是在初始化顺序方面。(提示:它们应该是常量) - Wyck
使用--std=c++17(如果是旧编译器,则使用--std=c++11)编译您的程序,编译将失败。 - einpoklum
// 这行代码没有显示任何错误 -- 是的,它确实有错误。(https://rextester.com/NXZDT64108) - PaulMcKenzie
4个回答

10

这两个示例在C++中都不符合规范。如果编译器没有检测到后者的问题,则说明它不符合标准。

为什么这里会有不同的行为?

您使用一种语言扩展,允许运行时长度自动数组。但不允许运行时长度静态数组。全局数组具有静态存储。

如果您使用的是GCC编译器,可以使用-pedantic命令行选项要求其符合标准。这是一个好主意,以便了解可移植性问题。


4

数组的大小必须是一个常量。您可以通过将 y 声明为 const 来解决这个问题。

const int y=5;
int arr[y]; 

关于为什么这在main中有效,是因为g++允许在块级作用域中使用变长数组作为扩展功能。然而,这不是标准C++。

0

两者都不应该使用,其中一个能工作是因为(如@eerorika所说)自动长度数组在运行时允许,但全局数组需要具有静态存储。

如果您想声明一个具有可变大小的数组(例如由std::cin给出),您可以按照以下方式进行:

int x;
std::cin >> x;
const int n = x;
float arr[n];

但是如果你想要设置它只包含零,使用float arr[n] = {0}是不行的(如果你需要向数组中的值添加一些内容,而不确定你是否已经设置了它),你需要像下面这样使用循环来实现

for(int i = 0; i < n; i++)
{
    arr[i] = 0;
}

1
你的示例仍然不正确,尽管使用了const。大小必须是编译时常量表达式。当然,从运行时输入得到的内容并不满足这一点。 - eerorika
“两者都不应该使用”这种说法是不合适的。一个人可能希望避免使用可变长度数组来编写可移植的C++代码。但是,为了实现所需的项目目标,一个人可能希望使用可变长度数组,即使牺牲了可移植性。这些目标的价值是主观和环境因素的,你不能确定另一个人的平衡点在哪里。 - Eric Postpischil
@EricPostpischil 您是正确的,但当您使用可变变量时,您可以更改它,出于安全原因最好将其保留为const。 - Misty

0

C++的类型系统以一种方式处理这些类似于C的数组,它从您的示例中定义了arr2的类型为int[5]。因此,是的,数组元素的数量是类型的一部分!

这对您在定义类似于C的数组时允许使用的内容施加了一些限制。即这个数字需要具有静态存储,需要是不可变的并且需要在编译时可用。

因此,您可能希望将代码更改为以下内容,这将具有另一个好处。它以正确的方式初始化数组:

int arr2[] = {0, 0, 0, 0, 0};   

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接