当我尝试运行它时,它给出了一个错误,说明变量中的值 a
不是恒定的。这对我来说没有意义,因为我明确地做了变量 a
不变。数组的大小是否必须更加恒定?只有意义 #define a 5
,或将其初始化为 int arr[5]
或使用 malloc
?我做了什么错了?
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;
}
在C中, const
应该读作 只读。它没有定义编译时间。
const int a = 5;
这里 a
是的 不 根据需要的常量表达式 C标准:
6.7.9初始化
4具有静态或线程存储持续时间的对象的初始化程序中的所有表达式都应是常量
表达式或字符串文字。
因此错误表明您正在使用C89 / C90编译器。您可以阅读用户的输入 a
并声明一个 可变长度数组,这是一个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)。因此,如果您使用的是不支持C99的编译器,则无法使用VLA。
例如,visual studio不完全支持所有C99和C11功能。虽然, Visual Studio 2015支持大多数C99功能,VLA不是其中之一。
但是相同的代码在C99和C11中编译没有任何问题:
$ gcc -Wall -Wextra -std=c99 -pedantic-errors t.c
$ gcc -Wall -Wextra -std=c11 -pedantic-errors t.c
这是因为在C99中添加了可变长度数组(VLA)。请注意,在C11标准中,VLA已经成为可选项。因此,实现可能不支持C11中的VLA。
你需要测试 __STDC_NO_VLA__
检查您的实现是否不支持VLA。
从 6.10.8.3条件特征宏
__STDC_NO_VLA__
整数常量1,用于表示实现不支持可变长度数组或可变
修改过的类型
我个人不使用VLA,因为如果数组大小相当大,则无法轻易找到分配失败。例如。
size_t size = 8*1024;
int arr[size];
在上面的片段中,如果 arr
分配失败,直到运行时才会知道它。什么是“足够小”的大小,内存分配取决于平台。所以在一台机器上,1MB的分配可能会成功,另一台可能会失败,更糟糕的是,没有办法抓住这个失败。
因此,VLA的使用是有限的,并且只能用于您知道在给定平台上始终成功的小型阵列。但是,我只需对数组大小进行硬编码并处理边界条件。
也许使用枚举来定义值 a
。
enum { a = 5 };
int arr [a];
也许这不是枚举的意图,但枚举的成员是最接近C中常量的东西。不同于使用定义所有内容的常见做法 #define
,知名度 a
受范围限制,这里它是相同的 arr
。
一个 const
- 限定变量与a不同 不断表达;常量表达式在编译时已知其值,而a const
- 限定变量(通常)不会(即使看起来应该如此)。
请注意,在C99及更高版本中,可以声明 可变长度数组,直到运行时才知道数组大小。您必须使用C99或更高版本的编译器,并且鉴于该功能在2011标准中是可选的,您必须检查功能宏以查看VLA是否可用:
static const int a = 10; // a is not a constant expression
#if defined( __STDC__ ) && defined ( __STDC_VERSION__ ) && __STDC_VERSION__ >= 199901L && !defined( __STDC_NO_VLA__ )
/**
* VLAs are available in this environment
*/
#define USE_VLA 1
#endif
#ifdef USE_VLA
int arr[a];
#else
/**
* VLAs are not available, either because it's a pre-1999 implementation,
* or it's a post-2011 implementation that does not support optional
* VLAs. We'll have to use dynamic memory allocation here, meaning we'll
* also need an explicit free call when we're done with arr
*/
int *arr = malloc( sizeof *arr * a );
#endif
...
do_something_interesting_with( a );
...
#ifndef USE_VLA
free( a );
#endif
至少在最近,微软的C编译器不支持VLA。他们一直在添加一些C99功能,例如混合声明和代码,因此最新版本可能支持VLA。我不知道。