可以在c的运行时确定数组的大小吗?

时间:2009-11-04 22:35:20

标签: c arrays memory-management size definition

据我所知,在编译c的时间之前,数组需要具有特定的大小。

我想知道为什么这段代码仍有效?

int s;
printf("enter the array size: ");
scanf("%d",&s);

int a[s]; // Isn't s value determined at run time?

6 个答案:

答案 0 :(得分:22)

需要使用ANSI 89 C了解数组大小。规范的99版本删除了此限制并允许使用可变大小的数组。

以下是没有此功能的GNU版本的文档

答案 1 :(得分:5)

如果你需要分配一个动态大小的数组,你必须使用malloc()从堆中获取它。

int *a = (int*)malloc(sizeof(int) * s)

答案 2 :(得分:1)

你在这里混淆了两件事。

1)确定已分配数组的大小(标题所暗示的):将sizeof()除以一个(例如,第一个)元素的大小:

 sizeof(a)/sizeof(a[0])

2)动态分配内存作为你的问题:

 int *a = (int*)malloc( s * sizeof(int) );

答案 3 :(得分:1)

C99语言规范支持此代码。 GCC编译器在C89 / 90模式下也支持此代码作为扩展。

所以,你问题的答案(为什么它“有效”)取决于你如何编译它。在一般情况下,这甚至不会由C89 / 90编译器编译。

答案 4 :(得分:1)

Variable Length Arrays以来,

C99已成为C语言的一部分。 但是它们已经成为C11中的一个特性 - 意味着符合C11的实现不需要提供它(尽管实际上所有支持C99的实现都确实在C11中提供了VLA)。

您可以检查您的实现是否未使用宏__STDC_NO_VLA__提供VLA(如果它在C99或C11编译模式中定义,那么您的实现不支持VLA)。 / p>

因此,在现代C(> = C99)中可以在运行时决定数组大小,并且下面的代码很好:

int s;
printf("Enter the array size: ");
scanf("%d", &s);
int a[s];

VLA的一个明显缺点是,如果s非常大并且a coud的分配失败。更糟糕的是,无法检查分配是否失败,并且您将遇到运行时错误(例如,段错误)。它本质上是undefined behaviour。所以如果数组大小太大则要避免使用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);

答案 5 :(得分:0)

了解内存如何由编译器分配给变量以便为您的问题提供正确答案非常重要。有两种模式可以将内存分配给变量,它可以在堆上,也可以在堆栈上。堆上的内存是动态分配的。因此,在堆上分配内存的变量可以在运行时给出它的大小。

在C的情况下,阵列在堆栈上被给予内存。为了在堆栈上提供内存,编译器在编译期间应该知道内存的大小。因此,在运行时,可以为堆栈上的变量留出大量内存。就C语言而言,这就是你无法在运行时决定数组大小的原因。