使用const int定义数组的大小

Kat*_*ith 11 c arrays size const

当我尝试运行它时,它给出了一个错误,说变量中的值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;
}
Run Code Online (Sandbox Code Playgroud)

P.P*_*.P. 9

在C中,const应该以只读方式读取.它没有定义编译时间.

const int a = 5;
Run Code Online (Sandbox Code Playgroud)

这里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];
    ^
Run Code Online (Sandbox Code Playgroud)

因为C89不支持VLA(尽管gcc支持它作为扩展,即使在C89/C90中也是如此).因此,如果您使用的是不支持C99的编译器,则无法使用VLA.例如,visual studio不完全支持所有C99和C11功能.尽管Visual Studio 2015支持大多数C99功能,但VGA并不是其中之一.

但是相同的代码在C99和C11中编译没有任何问题:

$ gcc -Wall -Wextra -std=c99 -pedantic-errors t.c
$ gcc -Wall -Wextra -std=c11 -pedantic-errors t.c
Run Code Online (Sandbox Code Playgroud)

这是因为在C99中添加了可变长度数组(VLA).请注意,VLA已在C11标准中成为可选项.因此,实现可能不支持C11中的VLA.您需要进行测试__STDC_NO_VLA__以检查实施是否不支持VLA.

6.10.8.3条件特征宏

__STDC_NO_VLA__
整型常量1,用于指示实现不支持可变长度数组或可变修改类型.

我个人不使用VLA,因为如果数组大小相当大,则无法轻易找到分配失败.例如

size_t size = 8*1024;
int arr[size];
Run Code Online (Sandbox Code Playgroud)

在上面的片段中,如果arr分配失败,则在运行时才会知道它.什么是"足够小"的大小,内存分配取决于平台.因此,在一台机器上,1MB的分配可能会成功,另一台可能会失败,更糟糕的是,没有办法抓住这个失败.

因此,VLA的使用是有限的,并且只能用于您知道在给定平台上始终成功的小型阵列.但是我只需要对数组大小进行硬编码并处理边界条件.