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

据我所知,在编译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版本删除了此限制并允许使用可变大小的数组。

这是没有此function的GNU版本的文档

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

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

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

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

你在这里混淆了两件事。

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

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

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

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

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

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

自C99以来, 可变长度数组已成为C语言的一部分。 但它们已经成为C11中的一个特性 – 这意味着符合C11标准的实现不需要提供它(尽管实际上所有支持C99的实现都确实在C11中提供了VLA)。

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

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

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

VLA的一个明显缺点是,如果s非常大并且coud的分配失败。 更糟糕的是,无法检查分配是否失败,并且您将遇到运行时错误(例如,段错误)。 它本质上是未定义的行为 。 因此,如果arrays大小太大,您希望避免使用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);