user-0 提问: 对const的两点疑问

回复:
user: user-1
content: 请给出完整的用于测试的程序，你用于测试的编译命令行及输出，以及你的编译器版本。

user: user-0
content: 引用 17 楼 fefe82 的回复:c11 draft N1570 6.7.6.2 Array declarators 2 If an identifier is declared as having a variably modified type, it shall be an ordinary identifier (as defined in 6.2.3), have no linkage, and have either block scope or function prototype scope. If an identifier is declared to be an object with static or thread storage duration, it shall not have a variable length array type.  "对结构体成员数组定义使用 const int 作为长度是不允许的。" 是我解读过度了，抱歉。 变长数组只能出现在 block scope 或 function prototype scope 。你现在的这个例子是在 block scope 的。  作为全局的变量或 struct 的定义是不行的。  ============================== 4 If the size is not present, the array type is an incomplete type. If the size is * instead of being an expression, the array type is a variable length array type of unspecified size, which can only be used in declarations or type names with function prototype scope;143) such arrays are nonetheless complete types. If the size is an integer constant expression and the element type has a known constant size, the array type is not a variable length array type; otherwise, the array type is a variable length array type. (Variable length arrays are a conditional feature that implementations need not support; see 6.10.8.3.)  这里要求如果不是 VLA (variable length array) ，长度必须的 interger constant expression.  ============================= 6.6 Constant expressions 6 An integer constant expression shall have integer type and shall only have operands that are integer constants, enumeration constants, character constants, sizeof expressions whose results are integer constants, _Alignof expressions, and floating constants that are the immediate operands of casts. Cast operators in an integer constant expression shall only convert arithmetic types to integer types, except as part of an operand to the sizeof or _Alignof operator.  这里限定了 integer constant expression实在是太厉害了，您能这么快精准的锁定，是因为通篇看过吗？？？我明天仔细研究一下，很荣幸与您交流。。。

user: user-0
content: 引用 17 楼 fefe82 的回复:c11 draft N1570 6.7.6.2 Array declarators 2 If an identifier is declared as having a variably modified type, it shall be an ordinary identifier (as defined in 6.2.3), have no linkage, and have either block scope or function prototype scope. If an identifier is declared to be an object with static or thread storage duration, it shall not have a variable length array type.  "对结构体成员数组定义使用 const int 作为长度是不允许的。" 是我解读过度了，抱歉。 变长数组只能出现在 block scope 或 function prototype scope 。你现在的这个例子是在 block scope 的。  作为全局的变量或 struct 的定义是不行的。  ============================== 4 If the size is not present, the array type is an incomplete type. If the size is * instead of being an expression, the array type is a variable length array type of unspecified size, which can only be used in declarations or type names with function prototype scope;143) such arrays are nonetheless complete types. If the size is an integer constant expression and the element type has a known constant size, the array type is not a variable length array type; otherwise, the array type is a variable length array type. (Variable length arrays are a conditional feature that implementations need not support; see 6.10.8.3.)  这里要求如果不是 VLA (variable length array) ，长度必须的 interger constant expression.  ============================= 6.6 Constant expressions 6 An integer constant expression shall have integer type and shall only have operands that are integer constants, enumeration constants, character constants, sizeof expressions whose results are integer constants, _Alignof expressions, and floating constants that are the immediate operands of casts. Cast operators in an integer constant expression shall only convert arithmetic types to integer types, except as part of an operand to the sizeof or _Alignof operator.  这里限定了 integer constant expression服了，只能膜拜一下了。最新的C标准。。。我以为这东西只有写编译器的人才看。。。待我仔细看一下。

user: user-2
content: 我在VS2012下测试均能通过  不过const不是真正的常量 ，他在内存中仍是按变量存（可以取地址），只是编译器作检查，而#define是真常量

user: user-1
content: 引用 16 楼 docterwg 的回复:[quote=引用 15 楼 fefe82 的回复:] 因为 C 不允许使用 const int 作为 integer constant expression 作为普通数组的长度定义。只有字面量（及 sizeof 等）是允许的。 同时，variable length array 只允许作为 局部变量。 对结构体成员数组定义使用 const int 作为长度是不允许的。 您说的这几个英文确实让我觉得您答在点子上。但您说const int 不能作为普通数组的长度定义，对结构体成员数组定义使用 const int 作为长度是不允许的。,我不这么认为，事实上，下面代码运行正确。 int main() {     const int length= 5;     int aa[length];     struct  {         int cc[length];     } bb;      printf( "%d %d\n", sizeof(aa) ,sizeof(bb.cc)); 	return 0; } 还有就是我手上只有K&R的书，没有其他参考书。想问问您，您的以上观点从哪获得？我下载了C99文档，可我的英文水平确实读它有些慢。。。[/quote]  c11 draft N1570 6.7.6.2 Array declarators 2 If an identifier is declared as having a variably modified type, it shall be an ordinary identifier (as defined in 6.2.3), have no linkage, and have either block scope or function prototype scope. If an identifier is declared to be an object with static or thread storage duration, it shall not have a variable length array type.  "对结构体成员数组定义使用 const int 作为长度是不允许的。" 是我解读过度了，抱歉。 变长数组只能出现在 block scope 或 function prototype scope 。你现在的这个例子是在 block scope 的。  作为全局的变量或 struct 的定义是不行的。  ============================== 4 If the size is not present, the array type is an incomplete type. If the size is * instead of being an expression, the array type is a variable length array type of unspecified size, which can only be used in declarations or type names with function prototype scope;143) such arrays are nonetheless complete types. If the size is an integer constant expression and the element type has a known constant size, the array type is not a variable length array type; otherwise, the array type is a variable length array type. (Variable length arrays are a conditional feature that implementations need not support; see 6.10.8.3.)  这里要求如果不是 VLA (variable length array) ，长度必须的 interger constant expression.  ============================= 6.6 Constant expressions 6 An integer constant expression shall have integer type and shall only have operands that are integer constants, enumeration constants, character constants, sizeof expressions whose results are integer constants, _Alignof expressions, and floating constants that are the immediate operands of casts. Cast operators in an integer constant expression shall only convert arithmetic types to integer types, except as part of an operand to the sizeof or _Alignof operator.  这里限定了 integer constant expression

user: user-0
content: 引用 15 楼 fefe82 的回复:因为 C 不允许使用 const int 作为 integer constant expression 作为普通数组的长度定义。只有字面量（及 sizeof 等）是允许的。 同时，variable length array 只允许作为 局部变量。 对结构体成员数组定义使用 const int 作为长度是不允许的。 您说的这几个英文确实让我觉得您答在点子上。但您说const int 不能作为普通数组的长度定义，对结构体成员数组定义使用 const int 作为长度是不允许的。,我不这么认为，事实上，下面代码运行正确。 int main() {     const int length= 5;     int aa[length];     struct  {         int cc[length];     } bb;      printf( "%d %d\n", sizeof(aa) ,sizeof(bb.cc)); 	return 0; } 还有就是我手上只有K&R的书，没有其他参考书。想问问您，您的以上观点从哪获得？我下载了C99文档，可我的英文水平确实读它有些慢。。。

user: user-1
content: 因为 C 不允许使用 const int 作为 integer constant expression 作为普通数组的长度定义。只有字面量（及 sizeof 等）是允许的。  同时，variable length array 只允许作为 局部变量。  对结构体成员数组定义使用 const int 作为长度是不允许的。  引用 12 楼 docterwg 的回复:[quote=引用 2 楼 fefe82 的回复:] 你不给程序，没有办法理解你的编译器输出啊。  我没理解你的意思，你要什么程序? 我说了main()里面没有东西，只有return 0; const int BlockSize = 20;//#define BlockSize 20 typedef struct _node {     int array[BlockSize];    struct _node* next;  } Node; int  main()  {return 0;} 程序编译不过去，我想知道为什么？ [/quote]

user: user-0
content: 引用 10 楼 xmnathan 的回复:是因为你的编译器还没支持这个吧R U Sure?

user: user-0
content: 引用 11 楼 ZiSheng 的回复:这个-std=c99在code：block中在哪添加？？？谢谢  Settings->Global compiler settings->Compiler settings->Other options->输入即可。伸手党要不要做的这么明显？

user: user-0
content: 引用 2 楼 fefe82 的回复:你不给程序，没有办法理解你的编译器输出啊。  我没理解你的意思，你要什么程序? 我说了main()里面没有东西，只有return 0; const int BlockSize = 20;//#define BlockSize 20 typedef struct _node {     int array[BlockSize];    struct _node* next;  } Node; int  main()  {return 0;} 程序编译不过去，我想知道为什么？

user: user-3
content: 引用 8 楼 docterwg 的回复:[quote=引用 7 楼 paschen 的回复:] [quote=引用 6 楼 docterwg 的回复:] [quote=引用 4 楼 user-6 的回复:] 和编译器有关系吧 这个在effective C++里面提到过 关于const 与#define  上述是C语言，不是C++，这两者对const处理不完全相同，好像C++更完善一些。[/quote]   在C语言中用const去修饰一个变量，表示这个变量是只读的，不可通过显式的调用a去修改a的值，并且此时a仍然是一个变量，不能等同于常量  const int n=5; int a[n];  这种方式在C语言中会报错，原因在于声明数组时数组的长度必须为一个constant，即常量，虽然n用const限定了，但n终究是一个变量，因此会报错;  但是在C++中不会报错，因为在C++中用const修饰过后，n就已经等同于一个常量了，因此可以通过。  摘自：http://www.cnblogs.com/dolphin0520/archive/2011/04/18/2020248.html[/quote]  版主可尝试一下，把你写的这个写在main()里面，看看编译能否通过。若通不过，加-std=c99，我的编译器可以编译过。[/quote]  这个-std=c99在code：block中在哪添加？？？谢谢

user: user-4
content: 是因为你的编译器还没支持这个吧

user: user-1
content: 引用 3 楼 docterwg 的回复:[quote=引用 2 楼 fefe82 的回复:] 请给出完整的用于测试的程序，你用于测试的编译命令行及输出，以及你的编译器版本。  main()函数里面什么也没有，只有return 0; ①②任意一个写在main()外都不行。  ---------------------------------------------------------------------针对①的----------------------------------------------------------------------------------------------------- 编译项目变更... -------- - 项目文件名: D:\C\项目1.dev - 编译器名: TDM-GCC 4.9.2 32-bit Release  生成 makefile... -------- - 文件名: D:\C\Makefile.win  正在处理makefile... -------- - makefile处理器: C:\Program Files (x86)\Dev-Cpp\MinGW64\bin\mingw32-make.exe - 命令: mingw32-make.exe -f "D:\C\Makefile.win" all  gcc.exe -c main.c -o main.o -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/include" -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/x86_64-w64-mingw32/include" -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/lib/gcc/x86_64-w64-mingw32/4.9.2/include" -m32 -std=gnu99  main.c:6:9: error: variably modified 'array' at file scope      int array[BlockSize];          ^  D:\C\Makefile.win:28: recipe for target 'main.o' failed  mingw32-make.exe: *** [main.o] Error 1   编译结果... -------- - 错误: 1 - 警告: 0 - 输出文件名: D:\C\项目1.exe - 输出大小: 101.6064453125 KiB - 编译时间: 0.45s --------------------------------------------------------------------针对②---------------------------------------------------------------------------------------------------- 编译项目变更... -------- - 项目文件名: D:\C\项目1.dev - 编译器名: TDM-GCC 4.9.2 32-bit Release  生成 makefile... -------- - 文件名: D:\C\Makefile.win  正在处理makefile... -------- - makefile处理器: C:\Program Files (x86)\Dev-Cpp\MinGW64\bin\mingw32-make.exe - 命令: mingw32-make.exe -f "D:\C\Makefile.win" all  gcc.exe -c main.c -o main.o -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/include" -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/x86_64-w64-mingw32/include" -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/lib/gcc/x86_64-w64-mingw32/4.9.2/include" -m32 -std=gnu99  main.c:5:1: error: initializer element is not constant  int g = gAll;   ^  D:\C\Makefile.win:28: recipe for target 'main.o' failed  mingw32-make.exe: *** [main.o] Error 1   编译结果... -------- - 错误: 1 - 警告: 0 - 输出文件名: D:\C\项目1.exe - 输出大小: 101.6064453125 KiB - 编译时间: 0.45s[/quote]  你不给程序，没有办法理解你的编译器输出啊。

user: user-0
content: 引用 7 楼 paschen 的回复:[quote=引用 6 楼 docterwg 的回复:] [quote=引用 4 楼 user-6 的回复:] 和编译器有关系吧 这个在effective C++里面提到过 关于const 与#define  上述是C语言，不是C++，这两者对const处理不完全相同，好像C++更完善一些。[/quote]   在C语言中用const去修饰一个变量，表示这个变量是只读的，不可通过显式的调用a去修改a的值，并且此时a仍然是一个变量，不能等同于常量  const int n=5; int a[n];  这种方式在C语言中会报错，原因在于声明数组时数组的长度必须为一个constant，即常量，虽然n用const限定了，但n终究是一个变量，因此会报错;  但是在C++中不会报错，因为在C++中用const修饰过后，n就已经等同于一个常量了，因此可以通过。  摘自：http://www.cnblogs.com/dolphin0520/archive/2011/04/18/2020248.html[/quote]  版主可尝试一下，把你写的这个写在main()里面，看看编译能否通过。若通不过，加-std=c99，我的编译器可以编译过。

user: user-2
content: 引用 6 楼 docterwg 的回复:[quote=引用 4 楼 user-6 的回复:] 和编译器有关系吧 这个在effective C++里面提到过 关于const 与#define  上述是C语言，不是C++，这两者对const处理不完全相同，好像C++更完善一些。[/quote]   在C语言中用const去修饰一个变量，表示这个变量是只读的，不可通过显式的调用a去修改a的值，并且此时a仍然是一个变量，不能等同于常量  const int n=5; int a[n];  这种方式在C语言中会报错，原因在于声明数组时数组的长度必须为一个constant，即常量，虽然n用const限定了，但n终究是一个变量，因此会报错;  但是在C++中不会报错，因为在C++中用const修饰过后，n就已经等同于一个常量了，因此可以通过。  摘自：http://www.cnblogs.com/dolphin0520/archive/2011/04/18/2020248.html

user: user-0
content: 引用 4 楼 user-6 的回复:和编译器有关系吧 这个在effective C++里面提到过 关于const 与#define  上述是C语言，不是C++，这两者对const处理不完全相同，好像C++更完善一些。

user: user-5
content: 赞同版主的看法！

user: user-6
content: 和编译器有关系吧 这个在effective C++里面提到过 关于const 与#define

user: user-0
content: 引用 2 楼 fefe82 的回复:请给出完整的用于测试的程序，你用于测试的编译命令行及输出，以及你的编译器版本。  main()函数里面什么也没有，只有return 0; ①②任意一个写在main()外都不行。  ---------------------------------------------------------------------针对①的----------------------------------------------------------------------------------------------------- 编译项目变更... -------- - 项目文件名: D:\C\项目1.dev - 编译器名: TDM-GCC 4.9.2 32-bit Release  生成 makefile... -------- - 文件名: D:\C\Makefile.win  正在处理makefile... -------- - makefile处理器: C:\Program Files (x86)\Dev-Cpp\MinGW64\bin\mingw32-make.exe - 命令: mingw32-make.exe -f "D:\C\Makefile.win" all  gcc.exe -c main.c -o main.o -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/include" -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/x86_64-w64-mingw32/include" -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/lib/gcc/x86_64-w64-mingw32/4.9.2/include" -m32 -std=gnu99  main.c:6:9: error: variably modified 'array' at file scope      int array[BlockSize];          ^  D:\C\Makefile.win:28: recipe for target 'main.o' failed  mingw32-make.exe: *** [main.o] Error 1   编译结果... -------- - 错误: 1 - 警告: 0 - 输出文件名: D:\C\项目1.exe - 输出大小: 101.6064453125 KiB - 编译时间: 0.45s --------------------------------------------------------------------针对②---------------------------------------------------------------------------------------------------- 编译项目变更... -------- - 项目文件名: D:\C\项目1.dev - 编译器名: TDM-GCC 4.9.2 32-bit Release  生成 makefile... -------- - 文件名: D:\C\Makefile.win  正在处理makefile... -------- - makefile处理器: C:\Program Files (x86)\Dev-Cpp\MinGW64\bin\mingw32-make.exe - 命令: mingw32-make.exe -f "D:\C\Makefile.win" all  gcc.exe -c main.c -o main.o -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/include" -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/x86_64-w64-mingw32/include" -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/lib/gcc/x86_64-w64-mingw32/4.9.2/include" -m32 -std=gnu99  main.c:5:1: error: initializer element is not constant  int g = gAll;   ^  D:\C\Makefile.win:28: recipe for target 'main.o' failed  mingw32-make.exe: *** [main.o] Error 1   编译结果... -------- - 错误: 1 - 警告: 0 - 输出文件名: D:\C\项目1.exe - 输出大小: 101.6064453125 KiB - 编译时间: 0.45s