2009-11-02 23 views
4

我有一种情况,我希望我的程序能够读取一些数字来定义二维数组的大小(用作矩阵)。我原本认为,要做到这一点的唯一方法是使用一个malloc调用把阵列上堆,是这样的:可以使用一个变量来定义栈中数组的大小c?

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指定此行为或只是一些海湾合作委员会在其自身在做什么?

回答

8

此功能在C99中添加。该数组在堆栈上分配的方式类似于您拨打alloca()时的方式。可能有一些细微的差异;检查您的编译器文档的信息。

GCC documentation对其实现进行了说明。

+2

但请注意,对此的支持很不明显。即使在GCC试图支持它一段时间,它显然是甚至到4.3版本(http://gcc.gnu.org/gcc-4.3/c99status.html) – 2009-11-02 19:06:21

+0

+1,是绝对正确的。这可能是C99中最有争议的一个。 – 2009-11-02 19:07:01

+2

请注意,你的堆栈通常比你的堆小得多。如果你想动态调整任何实际大小的数组,使用malloc()可能是一个好主意。还要记住,像所有本地(非静态)对象一样,这些数组一旦你的函数返回就会消失。 – 2009-11-02 19:15:43

3

C99添加了对变长数组(有时称为“VLA”)的支持。许多C编译器在C99之前也支持这一点。许多人也支持“分配”功能,即使做了同样的事情,但方式稍微不方便。

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

3

您应该对此感到惊讶,因为您可以在块的中间声明您的arr数组,因为您对其可变指定大小感到惊讶。两者都是C99语言规范的新功能。作为C89/90的延伸,GCC编译器都支持它们一段时间。但在“经典”ANSI C即C89/90中都不合法。

如果要编译在C89/90模式的代码(这是默认GCC),那么你确实处理GCC的东西是做根据自身。如果您使用-std=c99模式编译代码,那么您正在处理[相对]新的标准语言功能。

+1

除了'任何地方的声明'更常被看作C90和C++代码的扩展,而VLA并不常见。 – 2009-11-02 19:57:00

相关问题