难以理解C中的可变长度数组

时间:2012-04-08 11:58:21

标签: c arrays declaration

当我发现数据大小必须在声明时给出或者在运行时使用malloc从堆分配时,我正在读一本书。我在C中编写了这个程序:

#include<stdio.h>

int main() {
  int n, i;
  scanf("%d", &n);
  int a[n];
  for (i=0; i<n; i++) {
    scanf("%d", &a[i]);
  }
  for (i=0; i<n; i++) {
    printf("%d ", a[i]);
  }
  return 0;
}

此代码工作正常。

我的问题是这段代码是如何正常工作的。不是违反C的基本概念,数组大小必须在运行时之前声明,或者在运行时使用malloc()分配它。我没有做任何这些两件事,为什么它正常运作?

我的问题的解决方案是C99支持的可变长度数组,但是如果我玩我的代码并将语句int放入[n];在scanf(“%d,&amp; n)”之上;然后它停止工作为什么它如此。如果C支持可变长度数组?

4 个答案:

答案 0 :(得分:5)

C99标准支持variable length arrays。这些数组的长度是在运行时确定的。

答案 1 :(得分:3)

从C99起,您可以在块范围内声明可变长度数组。

示例:

void foo(int n)
{
    int array[n];

    // Initialize the array
    for (int i = 0; i < n; i++) {
        array[i] = 42;
    }
}

答案 2 :(得分:0)

只要您在使用之前声明了数组并为其分配了内存,C就会很高兴。 C的“特性”之一是它不验证数组索引,因此程序员有责任确保所有内存访问都有效。

答案 3 :(得分:0)

可变长度数组是C99中添加到C的一项新功能。

此处的“可变长度”是指数组的大小是在运行时而不是编译时确定的。这并不意味着数组的大小可以在创建后更改。逻辑上在声明数组的位置创建该数组。因此您的代码看起来像这样。

int n, i;

创建两个变量n和i。最初,这些变量未初始化。

scanf("%d", &n);

将值读入n。

int a[n];

创建一个数组“ a”,其大小为n的当前值。

如果交换第二步和第三步,则尝试创建一个数组,其大小由未初始化的值确定。这不可能很好地结束。

C标准没有确切指定数组的存储方式,但实际上大多数编译器(我相信有些例外)都会在堆栈上分配它。通常的方法是将栈指针复制到“帧指针”中,作为函数前导的一部分。这样一来,该函数就可以动态修改堆栈指针,同时跟踪其自身的堆栈框架。

可变长度数组是一项功能,应谨慎使用。编译器通常不对堆栈分配插入任何形式的溢出检查。操作系统通常在堆栈后插入一个“ gaurd页面”,以检测堆栈溢出并引发错误或增大堆栈,但是足够大的数组可以轻松跳过保护页面。