【问题标题】:Can a variable be used to define the size of an array on the stack in c?可以使用变量来定义c中堆栈上数组的大小吗?
【发布时间】:2009-11-02 18:57:42
【问题描述】:

我有一种情况,我希望我的程序读取一些数字,这些数字将定义二维数组(用作矩阵)的大小。我最初认为这样做的唯一方法是使用malloc 调用将数组放在堆上,如下所示:

matrixElement* matrix = malloc(sizeof(matrixElement) * numRows * numCols);

其中 numCols 和 numRows 是之前读入的整数,matrixElement 是一些任意类型。我的理由是简单地写:

matrixElement matrix[numRows][numCols];

不起作用,因为编译器无法知道要为函数调用分配多少堆栈空间。事实证明我错了,因为下面的代码编译并运行:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int x, y;
    scanf("%d", &x);
    scanf("%d", &y);

    double arr[x][y];

    printf("Made an array of size %d by %d, total memory %fKb\n", 
            sizeof(arr) / sizeof(arr[0]), 
            sizeof(arr[0]) / sizeof(arr[0][0]),
            (float) sizeof(arr) / 1024.0f);

    return 0;
}

为 x 和 y 输入足够大的数字后,这最终会产生段错误,但我也很惊讶我可以用这段代码创建一个 1000x1000 的数组。

谁能解释这里发生了什么?

编译器是否只是为数组分配了一堆空间,即使它不知道将使用多少?

这种行为是由 ANSI C 指定的,还是只是 gcc 自己在做的事情?

【问题讨论】:

    标签: c arrays


    【解决方案1】:

    此功能是在 C99 中添加的。数组在堆栈上的分配方式与调用alloca() 时的方式类似。可能会有一些细微的差别;检查您的编译器文档以获取信息。

    GCC documentation 有对其实现的描述。

    【讨论】:

    • 但请注意,对此的支持参差不齐。即使在已经尝试支持它一段时间的 GCC 中,它显然在 4.3 版之前也存在相当多的错误 (gcc.gnu.org/gcc-4.3/c99status.html)
    • +1,绝对正确。这可能是 C99 中最具争议的新增功能。
    • 请注意,您的堆栈通常比您的堆小得多。如果您想要任何实际大小的动态大小的数组,使用 malloc() 可能是一个好主意。还请记住,与所有本地(非静态)对象一样,一旦您的函数返回,这些数组就会消失。
    【解决方案2】:

    C99 添加了对可变长度数组(有时称为“VLA”)的支持。在 C99 之前,许多 C 编译器也支持此功能。许多人还支持“alloca”函数,它做同样的事情,虽然方式不太方便。

    典型的实现会分配“正确”的空间量。本质上,堆栈指针只是根据可变长度数组的大小进行调整。需要做一些额外的记录以确保堆栈指针在返回时“弹出”正确的数量,并且在正确的偏移量处访问放置在堆栈上的自动变量。

    【讨论】:

      【解决方案3】:

      您应该对您可以在块的中间声明您的arr 数组这一事实感到惊讶,因为您对其变量指定的大小感到惊讶。两者都是 C99 语言规范的新特性。一段时间以来,GCC 编译器都支持两者作为 C89/90 的扩展。但在“经典”ANSI C(即 C89/90)中两者都不合法。

      如果您在 C89/90 模式下编译代码(这是 GCC 的默认模式),那么您确实在处理 GCC 自行执行的操作。如果您在-std=c99 模式下编译您的代码,那么您正在处理[相对] 新的标准语言功能。

      【讨论】:

      • 除了“任何地方的声明”更常见地被视为对 C90 和 C++ 代码的扩展,而 VLA 并不常见。
      猜你喜欢
      • 2023-04-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-13
      • 2011-03-22
      • 1970-01-01
      • 2017-06-24
      • 2013-05-20
      • 1970-01-01
      相关资源
      最近更新 更多