在 C 中,const 应该被读作只读。它没有定义编译时间。
const int a = 5;
这里的a,不是C standard要求的常量表达式:
6.7.9 初始化
4 具有静态或线程存储持续时间的对象的初始化程序中的所有表达式应为常量
表达式或字符串文字。
所以错误表明您使用的是 C89/C90 编译器。您可以从用户那里读取a 的输入并声明variable length array,这是一个C99 功能,具有自动存储持续时间。
使用#define 是另一种方式。但它只是一个文本替换,并定义了一个具有自动存储持续时间的数组。和自己定义int arr[5];一样。
如果您想在动态存储(通常称为“堆”)上分配内存,则必须使用 malloc() 系列函数,它在程序执行期间将具有生命周期,直到您对其调用 free()。
(请注意,const 的这种行为仅在 C 中。C++ 在这方面有所不同,将按您的预期工作)。
如果我在 C89 中编译代码,它会失败:
#include <stdio.h>
int main(){
const int a = 5;
int i;
int arr [a];
for (i = 0; i < 5; i++) {
arr[i] = i * 2;
}
printf("%d", arr[1]);
return 0;
}
$ gcc -Wall -Wextra -std=c89 -pedantic-errors test.c
test.c: In function âmainâ:
test.c:7:4: error: ISO C90 forbids variable length array âarrâ [-Wvla]
int arr [a];
^
因为 C89 不支持 VLA(尽管 gcc 即使在 C89/C90 中也支持 an extension)。因此,如果您使用的编译器不支持 C99,那么您就不能使用 VLA。
例如,Visual Studio 并不完全支持所有 C99 和 C11 功能。虽然,Visual studio 2015 support most C99 features,VLA 不是其中之一。
但相同的代码在 C99 和 C11 中编译没有任何问题:
$ gcc -Wall -Wextra -std=c99 -pedantic-errors t.c
$ gcc -Wall -Wextra -std=c11 -pedantic-errors t.c
这是因为 C99 中添加了可变长度数组 (VLA)。请注意,VLA 在 C11 标准中已成为可选。因此,实现可能不支持 C11 中的 VLA。
您需要针对 __STDC_NO_VLA__ 进行测试,以检查您的实现是否不支持 VLA。
来自6.10.8.3 Conditional feature macros
__STDC_NO_VLA__
整数常量 1,意在表示实现不支持变长数组或变长
修改类型。
我个人不使用 VLA,因为如果数组大小相当大,则无法便携地找到分配失败。例如
size_t size = 8*1024;
int arr[size];
在上面的片段中,如果arr 分配失败,直到运行时你才会知道。内存分配取决于平台的“足够小”大小是多少。所以在一台机器上,1MB 分配可能会成功,而另一台机器可能会失败,更糟糕的是没有办法捕捉到这个失败。
因此,VLA 的使用受到限制,并且只能用于您知道在给定平台上总是会成功的小型阵列。但我会简单地对数组大小进行硬编码并处理边界条件。