代码之家  ›  专栏  ›  技术社区  ›  Graphics Noob

变量可以用来定义C语言中堆栈上数组的大小吗?

  •  4
  • Graphics Noob  · 技术社区  · 15 年前

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

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

    其中numcols和numrow是前面读取的整数,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数字输入,这最终会产生一个segfault,但我也很惊讶看到我可以用这个代码创建一个1000x1000数组。

    有人能解释一下这是怎么回事吗?

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

    这种行为是由ANSIC指定的,还是GCC自己做的?

    3 回复  |  直到 15 年前
        1
  •  8
  •   Carl Norum    15 年前

    此功能已添加到C99中。该数组在堆栈上的分配方式与如果调用 alloca() . 可能存在一些细微的差异;请查看编译器文档以获取信息。

    这个 GCC documentation 对它们的实现进行了描述。

        2
  •  3
  •   Laurence Gonsalves    15 年前

    C99增加了对可变长度阵列(有时称为“VLA”)的支持。许多C编译器在C99之前也对此提供了支持。许多人还支持一个“alloca”函数,它也做了同样的事情,尽管使用的方式稍微不方便。

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

        3
  •  3
  •   AnT stands with Russia    15 年前

    你应该对你能申报 arr 数组位于块的中间,您会惊讶于它的变量指定的大小。这两个都是C99语言规范的新特性。这两个版本都被GCC编译器作为C89/90的扩展支持了一段时间。但在“经典”的ANSI C,即C89/90中,两者都不合法。

    如果您是在c89/90模式下编译代码(这在gcc中是默认的),那么您确实在处理gcc自己正在做的事情。如果您正在编译代码 -std=c99 模式,您正在处理[相对]新的标准语言功能。