且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

使用const int定义数组的大小

更新时间:2023-02-05 20:52:17

在C语言中,const应该读为只读.它没有定义编译时间.

In C, const should be read as read-only. It doesn't define a compile time.

const int a = 5;

此处a不是 C标准:

6.7.9初始化
4具有静态或线程存储持续时间的对象的初始化程序中的所有表达式应为常数 表达式或字符串文字.

6.7.9 Initialization
4 All the expressions in an initializer for an object that has static or thread storage duration shall be constant expressions or string literals.

因此该错误表明您正在使用C89/C90编译器.您可以从用户那里读取a的输入,并声明一个可变长度数组,是一种C99功能,具有自动存储期限.

So the error indicates you are using a C89/C90 compiler. You can read the input from user for a and declare a variable length array, which is a C99-feature, which has automatic storage duration.

使用#define是另一种方法.但这只是文本替换,并定义了具有自动存储持续时间的数组.等同于自己定义int arr[5];.

Using #define is another way. But it's simply a textual replacement and defines an array with automatic storage duration. It's same as defining int arr[5]; yourself.

如果要在动态存储(通常称为堆")上分配内存,则必须使用

if you want to allocate memory on dynamic storage (commonly known as "heap"), you have to use malloc() family functions, which will have lifetime thoughout the program execution until you call free() on it.

(请注意,const的这种行为仅在C中.C++与此不同,并且将按预期工作).

(Note that this behaviour of const is only in C. C++ differs in this and will work as you expected).

如果我在C89中编译代码,它将失败并显示以下信息:

If I compile the code in C89, it fails with:

#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功能.虽然,

because C89 doesn't support VLAs (Although gcc supports it as an extension even in C89/C90). So if you are using a compiler that doesn't support C99 then you can't use VLAs. For example, visual studio doesn't fully support all C99 and C11 features. Although, Visual studio 2015 support most C99 features, VLAs are not one of them.

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

But the same code compiles in C99 and C11 without any problem:

$ 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.

It's because variable length arrays (VLAs) were added in C99. Note that VLAs have been made optional in C11 standard. So an implementation may not support VLAs in C11. You need to test against __STDC_NO_VLA__ to check if VLAs are not supported by your implementation.

来自 6.10.8.3条件特征宏 >

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

__STDC_NO_VLA__
The integer constant 1, intended to indicate that the implementation does not support variable length arrays or variably modified types.

我个人不使用VLA,因为如果阵列大小相当大,则无法移植地发现分配失败.例如

I personally do not use VLAs as the allocation failure can't be portably found if the array size is reasonably large. E.g.

size_t size = 8*1024;
int arr[size];

在上面的片段中,如果arr分配失败,则直到运行时您才知道它.内存分配取决于平台的足够小"的大小.因此,在一台计算机上,可能会成功分配1MB的内存,而在另一台计算机上可能会分配失败,更糟糕的是,没有办法解决此故障.

In the above fragment, if arr allocation failed, you won't know it until runtime. What's a "small enough" size for which the memory allocation is platform dependent. So on one machine, 1MB allocation may succeed and another it may fail and worse part is that there's no way to catch this failure.

因此,VLA的使用受到限制,并且只能与已知在给定平台上总是可以成功使用的小型阵列一起使用.但是在那种情况下,我只需要对数组大小进行硬编码,并注意边界条件.

Thus the use of VLAs is limited and can only be used with small arrays that you know will always succeed on a given platform. But in that I would simply hard-code the array size and take care of the boundary conditions.