为什么int x 错误,其中n是一个常量值?
我不明白为什么这样做是错误的:
const int n = 5; int x[n] = { 1,1,3,4,5 };  即使n已经是一个常量值。 
虽然这样做似乎是正确的GNU编译器:
 const int n = 5; int x[n]; /*without initialization*/ 
我知道C99的VLA特性,我认为它与发生的事情有关,但我只需要澄清一下在后台发生的事情。
 关键要记住的是, const和“constant”意味着两个完全不同的东西。 
  const关键字的意思是“只读”。  常量是数字文字,如42或1.5 (或枚举或字符常量)。  常量expression式是可以在编译时评估的特殊expression式,如2 + 2 。 
所以给了一个声明:
 const int n = 5; 
 expression式n表示对象的值,并不被视为常量expression式。 一个典型的编译器会优化对n的引用,用与文字5相同的代码replace它,但这不是必需的 – 而且expression式是否是常量的规则是由语言决定的,而不是由目前的编译器。 
  const (只读)和常量 (在编译时评估)之间的区别的一个例子是: 
 const size_t now = time(NULL); 
  const关键字意味着在初始化之后,你不允许修改now的值,但是直到运行时才能计算出time(NULL)的值。 
所以这:
 const int n = 5; int x[n]; 
 在C语言中比在没有const关键字的情况下更有效。 
 语言可能 (和恕我直言,可能应该)评价n作为一个常量的expression; 它只是没有这样定义。  (C ++确实有这样一个规则;请参阅C ++标准或关于血腥细节的体面参考。) 
 如果你想要一个名为5常量,最常用的方法是定义一个macros: 
 #define N 5 int x[N]; 
另一种方法是定义一个枚举常量:
 enum { n = 5 }; int x[n]; 
 枚举常量是常量expression式,并且始终为inttypes(这意味着此方法对于int以外的types不起作用)。 这可以说是滥用enum机制。 
从1999年的标准开始,可以用一个非常数的大小定义一个数组; 这是一个VLA或可变长度的数组。 这样的数组只能在块范围中使用,并且可能没有初始化器(因为编译器无法检查初始化器是否具有正确数量的元素)。
但是给你的原始代码:
 const int n = 5; int x[n] = { 1,1,3,4,5 }; 
您可以让编译器从初始值设定项中推断出长度:
 int x[] = { 1,1,3,4,5 }; 
然后你可以从数组的大小计算长度:
 const int x_len = sizeof x / sizeof x[0]; 
为什么
int x[n]是错误的,其中n是一个常量值?
  n不是一个常数。  const只承诺n是一个'只读'variables,在程序执行过程中不应该被修改。 
 请注意,在c中 ,与c ++不同, const限定variables不是常量。 因此,声明的数组是一个可变长度的数组。 
 您不能使用初始化程序列表来初始化可变长度数组。 
C11-§6.7.9/ 3:
要初始化的实体的types应该是未知大小的数组或不是可变长度数组types的完整对象types 。
 你可以使用#define或者enum使n成为一个常量 
 #define n 5 int x[n] = { 1,1,3,4,5 }; 
如果您正在彻底地初始化一个数组,那么让编译器推断数组大小会更简单,更安全,更易于维护:
 int x[] = { 1,1,3,4,5 }; const int n = sizeof(x) / sizeof(*x) ; 
然后要更改数组大小,只需更改初始化程序的数量,而不是更改大小和初始化程序列表以匹配。 特别有用的时候有很多的初始化。
 即使n是一个const ,除非你想创build一个VLA,否则你不能用它来定义一个数组的大小。 但是,您不能使用初始化程序列表来初始化VLA。 
使用macros来创build一个固定大小的数组。
 #define ARRAY_SIZE 5 int x[ARRAY_SIZE] = { 1,1,3,4,5 }; 
 你的代码在语义上与myfunc()不同: 
 void myfunc(const int n) { int x[n] = { 1,1,3,4,5 }; printf("%d\n", x[n-1]); *( (int *) &n) = 17; // Somewhat less "constant" than hoped... return ; } int main(){ myfunc(4); myfunc(5); myfunc(6); // Haven't actually tested this. Boom? Maybe just printf(noise)? return 0; } 
  n真的是所有这一切常数? 你认为编译器应该为x[]分配多less空间(因为编译器的工作是这样做的)? 
 正如其他人指出的那样,cv-qualifier const并不意味着“在编译期间和在所有时间之后的值”。 这意味着“本地代码不应该改变(尽pipe可以)”的值。