据我所知,在 c 中编译时间之前,数组需要具有特定的大小。
我想知道为什么这段代码仍然有效?
int s;
printf("enter the array size: ");
scanf("%d",&s);
int a[s]; // Isn't s value determined at run time?
据我所知,在 c 中编译时间之前,数组需要具有特定的大小。
我想知道为什么这段代码仍然有效?
int s;
printf("enter the array size: ");
scanf("%d",&s);
int a[s]; // Isn't s value determined at run time?
ANSI 89 C 需要知道数组大小。规范的 99 版本删除了这个限制并允许可变大小的数组。
这是该功能的 GNU 版本的文档
自C99以来,可变长度数组一直是 C 语言的一部分。但是它们已作为 C11 中的一个可选功能-这意味着符合 C11 的实现不需要提供它(尽管实际上所有支持 C99 的实现都肯定在 C11 中提供 VLA)。
您可以使用宏检查您的实现是否不提供 VLA __STDC_NO_VLA__
(如果它是在 C99 或 C11 编译模式中定义的,那么您的实现不支持 VLA)。
因此,在现代 C (>= C99) 中可以在运行时确定数组大小,并且下面的代码很好:
int s;
printf("Enter the array size: ");
scanf("%d", &s);
int a[s];
VLA 的一个明显缺点是 ifs
非常大,并且分配a
可能会失败。更糟糕的是,没有办法检查分配是否失败,您会遇到运行时错误(例如,segfault)。它本质上是未定义的行为。因此,如果数组大小太大,您要避免使用 VLA。基本上,当有疑问时,去动态内存分配(见下文)。
与其他相比,VLA 的另一个问题要严重得多,即它们具有自动存储持续时间(也称为“堆栈分配”)。因此,如果您想要一些持续时间更长的东西,然后是声明 VLA 的块范围,那么 VLA 将无济于事。
同样相关的是C89中没有 VLA 。所以使用动态内存分配是唯一的方法。虽然,有一些非标准的扩展,例如alloca()
类似于 VLA 并且具有与 VLA 相同的缺点)。
int s;
printf("enter the array size: ");
scanf("%d",&s);
int *a = malloc(s * sizeof *a);
...
free(a);
如果你需要分配一个动态大小的数组,你必须使用 malloc() 从堆中获取它。
int *a = malloc(sizeof(int) * s)
你在这里混淆了两件事。
1)确定已分配数组的大小(您的标题暗示):将sizeof()
总数除以一个(例如,第一个)元素的大小:
sizeof(a)/sizeof(a[0])
2)根据您的问题动态分配内存:
int *a = (int*)malloc( s * sizeof(int) );
此代码受 C99 语言规范支持。C89/90 模式下的 GCC 编译器也支持此代码作为扩展。
因此,您的问题的答案(为什么它“有效”)取决于您如何编译它。在一般情况下,这甚至不会被 C89/90 编译器编译。
了解编译器如何将内存分配给变量以正确回答您的问题很重要。内存分配给变量有两种模式,可以在堆上,也可以在栈上。堆上的内存是动态分配的。因此,在堆上分配内存的变量可以在运行时指定其大小。
在 C 的情况下,数组在堆栈上被赋予内存。为了在堆栈上提供内存,编译器在编译时应该知道内存的大小。因此,在运行期间,可以为堆栈上的变量留出大量内存。这就是就 C 语言而言,您无法在运行时决定数组大小的原因。