当我发现数据大小必须在声明时给出或者在运行时使用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支持可变长度数组?
答案 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)
答案 3 :(得分:0)
可变长度数组是C99中添加到C的一项新功能。
此处的“可变长度”是指数组的大小是在运行时而不是编译时确定的。这并不意味着数组的大小可以在创建后更改。逻辑上在声明数组的位置创建该数组。因此您的代码看起来像这样。
int n, i;
创建两个变量n和i。最初,这些变量未初始化。
scanf("%d", &n);
将值读入n。
int a[n];
创建一个数组“ a”,其大小为n的当前值。
如果交换第二步和第三步,则尝试创建一个数组,其大小由未初始化的值确定。这不可能很好地结束。
C标准没有确切指定数组的存储方式,但实际上大多数编译器(我相信有些例外)都会在堆栈上分配它。通常的方法是将栈指针复制到“帧指针”中,作为函数前导的一部分。这样一来,该函数就可以动态修改堆栈指针,同时跟踪其自身的堆栈框架。
可变长度数组是一项功能,应谨慎使用。编译器通常不对堆栈分配插入任何形式的溢出检查。操作系统通常在堆栈后插入一个“ gaurd页面”,以检测堆栈溢出并引发错误或增大堆栈,但是足够大的数组可以轻松跳过保护页面。