C语言 可以使用 const 变量在 C 中声明数组的大小吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18848537/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Can a const variable be used to declare the size of an array in C?
提问by user1901196
Why does the following code throw an error?
为什么下面的代码会抛出错误?
const int a = 5;
int b[a]={1,2,3,4,5};
And also when I tried to compile the above code without "const" keyword, I got the same error:
而且当我试图在没有“const”关键字的情况下编译上面的代码时,我得到了同样的错误:
int a = 5;
int b[a]={1,2,3,4,5};
why is it so? What is the mistake that I am doing here?
为什么会这样?我在这里做的错误是什么?
And also another question: When are constants replaced with their actual values in a code, i.e if I declare a variable say: const int x= 5; I know that no memory is allocated in RAM for the variable x, but constant variable area in ROM holds the value 5 and that x is simply replaced by the value 5 everywhere x appears in the code. But when does this happen? Compilation time? Boot up time? Preprocessing time?
还有另一个问题:什么时候常量在代码中用它们的实际值替换,即如果我声明一个变量说:const int x= 5; 我知道在 RAM 中没有为变量 x 分配内存,但是 ROM 中的常量变量区域保存值 5,并且 x 在代码中出现的任何地方都被值 5 替换。但是什么时候会发生这种情况呢?编译时间?开机时间?预处理时间?
PS: I am talking about Embedded C (running on a Microcontroller etc), not C running on my desktop. So the embedded system is bound to have a ROM (Flash, EEPROM...). What would happen then?
PS:我说的是嵌入式 C(在微控制器等上运行),而不是在我的桌面上运行的 C。所以嵌入式系统必然要有ROM(Flash、EEPROM...)。那会发生什么?
回答by Kerrek SB
It's simply a limitation of the language. The sizes of statically-bounded arrays need to be constant expressions, and unfortunately in C that's only something like a literal constant or a sizeofexpression or such like, but nota const-typed variable.
这只是语言的限制。静态界定阵列的尺寸需要是常量表达式,不幸的是用C,这只是像一个常量或sizeof表达式或类似,但不是一个const-typed变量。
(As Simon pointed out, since C99 there are also runtime-boundedarrays, or "variable-length arrays", whose size can be given by the value of any variable. But that's a different animal.)
(正如 Simon 指出的那样,从 C99 开始,还有运行时有界数组,或“可变长度数组”,其大小可以由任何变量的值给出。但那是另一种动物。)
You may be interested to hear that the rules are different in C++, where a static const intis indeed a constant expression, and C++11 even adds a new keyword, constexpr, to allow even more general use of constant expressions which encompass more things whose value "could reasonably be determined at compile time".
您可能有兴趣听到 C++ 中的规则不同,其中 astatic const int确实是一个常量表达式,而 C++11 甚至添加了一个新关键字constexpr,以允许更一般地使用包含更多值的事物的常量表达式“可以在编译时合理地确定”。
回答by Jens
In C, constis a misnomer for read-only. constvariables can change their value, e.g. it is perfectly okay to declare
在 C 中,const是read-only的用词不当。const变量可以改变它们的值,例如声明是完全可以的
const volatile int timer_tick_register; /* A CPU register. */
which you can read and get a different value with each read, but not write to. The language specification thus treats constqualified objects notas constant expressions suitable for array sizes.
您可以读取并在每次读取时获得不同的值,但不能写入。因此,语言规范把const合格的对象不为适用于数组大小常量表达式。
回答by Jimbo
EDIT: Just read on wikipedia that C11 has relegated variable length arrays to an optionalfeature :( Doh! The first half of the post may not be that useful but the second half answers some of your other questions :)
编辑:刚刚在维基百科上读到 C11 已将可变长度数组降级为一个可选功能:( Doh!帖子的前半部分可能没有那么有用,但后半部分回答了您的其他一些问题 :)
As an extra to Kerrek SB's post, C99 (ISO/IEC 9899:1999) does have the concept of a variable length array. The standard gives the following example:
作为 Kerrek SB 帖子的补充,C99 (ISO/IEC 9899:1999) 确实具有可变长度数组的概念。该标准给出了以下示例:
#include <stddef.h>
size_t fsize3(int n)
{
char b[n+3]; // variable length array
return sizeof b; // execution time sizeof
}
The sizeofoperator is extended as follows:
的sizeof操作者被扩展如下:
The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The size is determined from the type of the operand. The result is an integer. If the type of the operand is a variable length array type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an integer constant.
sizeof 运算符产生其操作数的大小(以字节为单位),它可以是表达式或类型的括号名称。大小由操作数的类型决定。结果是一个整数。如果操作数的类型是变长数组类型,则对操作数求值;否则,不计算操作数并且结果是整数常量。
Another nice example can be found on wikipedia.
另一个很好的例子可以在wikipedia上找到。
Note that statically declared cannot be variable length arrays.
请注意,静态声明不能是变长数组。
As for some of your other questions:
至于你的其他一些问题:
Q: When are constants replaced with their actual values in a code?
问:什么时候常量在代码中被替换为它们的实际值?
If the constant is a const variable then it may never be "replaced" and could always be accessed as an area of memory. This is because the address-of operator &still has to work with the variable. However, if the variable address is never used then it can be "replaced" and have no memory allocated. From the C standard:
如果常量是一个 const 变量,那么它可能永远不会被“替换”,并且总是可以作为内存区域访问。这是因为 address-of 运算符&仍然必须使用变量。但是,如果变量地址从未使用过,则可以“替换”它并且不分配内存。从 C 标准:
The implementation may place a const object that is not volatile in a read-only region of storage. Moreover, the implementation need not allocate storage for such an object if its address is never used.
该实现可以将一个非易失性的 const 对象放在存储的只读区域中。此外,如果从未使用过它的地址,则实现不需要为这样的对象分配存储空间。
Next question...
下一个问题...
Q: I know that no memory is allocated in RAM for the variable x, but constant variable area in ROM holds the value 5
问:我知道 RAM 中没有为变量 x 分配内存,但 ROM 中的常量变量区域保存值 5
This depends on your system. If you have ROM and the compiler knows where ROM is located then it may well be placed in ROM. If there is no ROM the only choice the compiler (well linker really) will have is RAM.
这取决于您的系统。如果您有 ROM 并且编译器知道 ROM 的位置,那么它很可能被放置在 ROM 中。如果没有 ROM,编译器(实际上是链接器)唯一的选择就是 RAM。
Q: x is simply replaced by the value 5 everywhere x appears in the code. But when does this happen? Compilation time? Boot up time? Preprocessing time?
问:在代码中出现 x 的任何地方,x 都被简单地替换为值 5。但是什么时候会发生这种情况呢?编译时间?开机时间?预处理时间?
As noted, this rather depends on how the constant is used. If the address of the const variable is never used and the compiler is clever enough, then at complilation time. Otherwise the "replacement" never occurs and it is a value with a location in memory; in this case the placement of the variable in memory happens at link time. It will neveroccur during preprocessing.
如前所述,这取决于如何使用常量。如果从不使用 const 变量的地址并且编译器足够聪明,那么在编译时。否则“替换”永远不会发生,它是一个在内存中具有位置的值;在这种情况下,变量在内存中的放置发生在链接时。它永远不会在预处理期间发生。
回答by Yuriy
Maybe it is worth to mention, here you could use
也许值得一提,在这里你可以使用
int b[] = {1, 4, 5};
In case you will need number of elements
如果您需要多个元素
size_t sz = sizeof(b)/sizeof(b[0]);
I believe it is up to tool chain, to decide where to store constants, flash or RAM
我相信这取决于工具链,决定在哪里存储常量、闪存或 RAM

