可以使用变量来定义c中堆栈上数组的大小吗?

时间:2009-11-02 18:57:43

标签: c arrays

我有一种情况,我希望我的程序读取一些数字,这些数字将定义二维数组的大小(用作矩阵)。我最初认为,唯一的方法是使用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自己做的事情?

3 个答案:

答案 0 :(得分:8)

此功能已在C99中添加。数组在堆栈上分配的方式类似于调用alloca()时的方式。可能存在一些微妙的差异;检查编译器文档以获取信息。

GCC documentation描述了它们的实现。

答案 1 :(得分:3)

C99增加了对可变长度数组(有时称为“VLA”)的支持。许多C编译器在C99之前也支持这一点。许多人还支持一个“alloca”函数,它做了同样的事情,但是方式稍差一点。

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

答案 2 :(得分:3)

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

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