为什么在逗号运算符(例如下面的示例)中指定的表达式不被视为常量表达式?
例如,
int a = (10,20) ;
在全局范围内给出时会产生错误“初始化程序不是常量”,尽管由逗号运算符分隔的两个表达式都是常量(常量表达式)。为什么整个表达式不被视为常量表达式?为了澄清,我已阅读What does the ‘,’ operator do in C?和Uses of C comma operator。他们没有涉及逗号运算符的这个方面。
答案 0 :(得分:33)
ISO C99标准的6.6/3
部分,“常量表达式”是您需要的部分。它声明:
常量表达式不应包含赋值,递增,递减,函数调用, 或逗号运算符,除非它们包含在不是的子表达式中 评价。
在ISO的C99基本原理文档中,有一个小片段:
整数常量表达式必须只涉及在转换时可知的数字,以及没有副作用的运算符。
而且,如果您不依赖副作用,那么在所有中使用逗号运算符毫无意义,那么它在常量表达式中是无用的。
由此,我的意思是两个代码段之间完全没有区别:
while (10, 1) { ... }
while (1) { ... }
因为10
实际上并没有做任何事情。事实上,
10;
是一个完全有效的,但不是很有用的C语句,大多数人在他们更好地了解语言之前都不会理解。
然而,是这两个陈述之间的区别:
while ( 10, 1) { ... }
while (x=10, 1) { ... }
后者使用逗号运算符会产生副作用,即将变量x
设置为10
。
至于为什么他们不喜欢常量表达式中的副作用,常量表达式的全部意义在于它们可以在编译时进行求值而无需执行环境 - ISO对转换(编译时)进行了区分和执行(运行时)环境。
关于为什么ISO决定不要求编译器提供执行环境信息(除limits.h
之类的头文件中包含的东西之外)的线索可以在理由文档中稍后找到:
然而,虽然实现肯定允许在翻译和执行环境中产生完全相同的结果,但要求这被认为是许多交叉编译器的不可容忍的负担。
换句话说,ISO不希望交叉编译器的制造商为每个可能的目标承担执行环境的负担。
答案 1 :(得分:6)
(10,20)
不是常量按定义表达。
基本原理必须是因为逗号表达式的第一部分的值不是使用它只是因为它的副作用,并且常量表达式没有副作用。
答案 2 :(得分:0)
编译器不会将其视为常量表达式,因为变量是自动的。允许在运行时进行评估并获取值。尝试使变量成为静态,您将看到相同的错误消息,因为编译器将需要一个时间的常量表达式。
答案 3 :(得分:-2)
gcс接受这个:
int a = (10,20) ;
int main() {
printf("%d\n",a);
}
并打印20
。可能这是你的编译器的问题?