Yah*_*aly 38 c arrays const c99
我不明白为什么这样做是错的:
const int n = 5;
int x[n] = { 1,1,3,4,5 };
Run Code Online (Sandbox Code Playgroud)
即使n已经是const值.
虽然这样做似乎适合GNU编译器:
const int n = 5;
int x[n]; /*without initialization*/
Run Code Online (Sandbox Code Playgroud)
我知道C99的VLA功能,我认为这与正在发生的事情有关,但我只需要澄清背景中发生的事情.
Kei*_*son 36
要记住的关键是,const"常数"意味着两个完全不同的东西.
该const关键字实际上意味着"只读".甲常数是数字文字,如42或1.5(或枚举或字符常数).甲常量表达式是一种特定类型的表达式,可以在编译时进行评估,如2 + 2.
所以给出一个声明:
const int n = 5;
Run Code Online (Sandbox Code Playgroud)
表达式n指的是对象的值,并且它不被视为常量表达式.典型的编译器将优化引用n,用它用于文字的相同代码替换它5,但这不是必需的 - 表达式是否是常量的规则是由语言决定的,而不是由当前的聪明性决定的.编译器.
const(只读)和常量(在编译时评估)之间的区别示例是:
const size_t now = time(NULL);
Run Code Online (Sandbox Code Playgroud)
该const关键字意味着你不允许修改的值now初始化后,但价值time(NULL)显然不能被计算到运行时.
所以这:
const int n = 5;
int x[n];
Run Code Online (Sandbox Code Playgroud)
在C中没有比没有const关键字更有效.
语言可以(和恕我直言可能应该)n作为一个常量表达式进行评估; 它只是没有这样定义.(C++确实有这样的规则;请参阅C++标准或关于血腥细节的体面参考.)
如果你想要一个带有值的命名常量5,最常见的方法是定义一个宏:
#define N 5
int x[N];
Run Code Online (Sandbox Code Playgroud)
另一种方法是定义枚举常量:
enum { n = 5 };
int x[n];
Run Code Online (Sandbox Code Playgroud)
枚举常量是常量表达式,并且始终是类型int(这意味着此方法不适用于除其他类型之外的类型int).它可以说是对enum机制的滥用.
从1999年标准开始,可以用非常数大小定义数组; 这是一个VLA或可变长度数组.此类数组仅在块作用域中被允许,并且可能没有初始化器(因为编译器无法检查初始化程序是否具有正确数量的元素).
但鉴于您的原始代码:
const int n = 5;
int x[n] = { 1,1,3,4,5 };
Run Code Online (Sandbox Code Playgroud)
你可以让编译器从初始化器中推断出长度:
int x[] = { 1,1,3,4,5 };
Run Code Online (Sandbox Code Playgroud)
然后,您可以从数组的大小计算长度:
const int x_len = sizeof x / sizeof x[0];
Run Code Online (Sandbox Code Playgroud)
hac*_*cks 21
为什么
int x[n]是错的地方n是const价值?
n不是一个常数.const只承诺n是一个'只读'变量,在程序执行期间不应该修改.
请注意,在c中,与c ++不同,const限定变量不是常量.因此,声明的数组是一个可变长度数组.
您不能使用初始化列表来初始化可变长度数组.
C11-§6.7.9/ 3:
要初始化的实体的类型应为未知大小的数组或不是可变长度数组类型的完整对象类型.
您可以使用#define或enum创建n常量
#define n 5
int x[n] = { 1,1,3,4,5 };
Run Code Online (Sandbox Code Playgroud)
如果您对数组进行了详尽的初始化,那么让编译器推断出数组大小会更容易,更安全,更易于维护:
int x[] = { 1,1,3,4,5 };
const int n = sizeof(x) / sizeof(*x) ;
Run Code Online (Sandbox Code Playgroud)
然后,要更改数组大小,您只需更改初始化程序的数量,而不是更改大小和初始化列表以匹配.当有许多初始化程序时特别有用.