【问题标题】:Why should global array size be an integer constant?为什么全局数组大小应该是一个整数常量?
【发布时间】:2020-06-22 12:52:10
【问题描述】:

在 C++ 中,我尝试声明某个大小的全局数组。我得到了错误:

数组边界在']'标记之前不是整数常量

但是当我在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.
}

编辑:许多人认为这个问题与Getting error "array bound is not an integer constant before ']' token" 重复。但这个问题并没有回答为什么会有不同的行为。

【问题讨论】:

  • 即使在main,也是不合法的,它使用VLA扩展。
  • all 数组的边界,在 C++ 中,需要有一个值,该值在编译期间是已知的。如果这样的代码,当你的编译器“接受”main 时:你正在使用编译器扩展,它允许 VLA 进行编译,即使它们不受 C++ 标准的支持。
  • 不要将“没有编译器错误”与“工作正常”混淆。在这种情况下,“工作正常”意味着您的代码依赖于非标准编译器提供的扩展,即它是好的,但它不是可移植的 c++
  • 为什么不将yx 声明为const?需要修改yx的值吗?希望不会,因为这引发了很多关于arrarr2 应该有多大的问题——尤其是对初始化顺序的表示。 (提示:它们应该是常量)
  • --std=c++17(或者--std=c++11,如果它是一个旧的编译器)编译你的程序,编译会失败。

标签: c++ variable-length-array


【解决方案1】:

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

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

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

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

【讨论】:

    【解决方案2】:

    两者都不应该使用,一个可行,因为(正如@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;
    }
    

    【讨论】:

    • 尽管使用了 const,但您的示例仍然不正确。大小必须是编译时常量表达式。你从运行时输入中得到的东西当然不能满足这一点。
    • “两者都不应该使用”的说法是不恰当的。人们可能希望避免使用可变长度数组来编写可移植的 C++ 代码。人们可能希望以牺牲可移植性为代价使用可变长度数组来实现所需的项目目标。这些目标的价值是主观的和间接的,你不能说其他人的平衡点在哪里。
    • @EricPostpischil 你是对的,但是当你使用可变变量时,你可以更改它,出于安全原因,最好将其保留为 const
    【解决方案3】:

    这两个例子在 C++ 中都是非良构的。如果编译器不诊断后者,则它不符合标准。

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

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

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

    【讨论】:

      【解决方案4】:

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

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

      至于为什么这在main 中起作用,g++ 确实允许块范围内的可变长度数组作为扩展。然而,它不是标准的 C++。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-04-28
        • 2018-05-04
        • 1970-01-01
        • 2020-05-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多