C逗号运算符
为什么在逗号运算符(如下面的例子)中指定的expression式不被视为常量expression式?
例如,
int a = (10,20) ;
当在全局范围中给出时会产生一个错误“初始化器不是一个常量”,尽pipe用逗号分隔的两个expression式都是常量(常量expression式)。 为什么整个expression式不被视为一个常量expression式? 为了澄清,我已经阅读了C中'''操作符是做什么的? 和C逗号运算符的用法 。 他们还没有处理这个逗号运算符的方面。
ISO C99标准的第6.6/3
节“常量expression式”是您需要的部分。 它指出:
常量expression式不得包含赋值,增量,减量,函数调用或逗号运算符,除非它们包含在未评估的子expression式中。
在ISO的C99基本原理文件中,有这个小片段:
整数常量expression式只能包含翻译时可以识别的数字,而操作符则不会有副作用。
而且,因为如果不依赖副作用,根本就没有必要使用逗号运算符,所以在常量expression式中是无用的。
那么,我的意思是这两个代码段之间绝对没有区别:
while (10, 1) { ... } while (1) { ... }
因为10
实际上没有做任何事情。 事实上,
10;
C语句是一个完全有效的,虽然不是很有用的C语言,大多数人直到更好地了解语言才能理解。
然而,这两种说法有所不同:
while ( 10, 1) { ... } while (x=10, 1) { ... }
逗号运算符的后一个用法是将variablesx
设置为10
的副作用。
至于为什么他们不喜欢常量expression式中的副作用,常量expression式的全部意义在于它们可以在编译时进行评估而不需要执行环境–ISO在转换(编译时)和执行运行时间)环境。
关于为什么ISO决定不要求编译器提供执行环境信息(除了在诸如limits.h
头文件中包含的东西以外)的线索可以在基本原理文档稍后的部分中find:
然而,虽然实现当然可以在翻译和执行环境中产生完全相同的结果,但是要求这样做被认为是许多交叉编译器难以承受的负担。
换句话说,ISO不希望交叉编译器的制造商承担为每个可能的目标带来执行环境的负担。
(常数expression式)指出,常数expression式不应包含逗号运算符(除非未评估的子expression式的一部分),所以(10,20)
不是定义的常量expression式。
基本原理必须是,因为逗号expression式的第一部分的价值不被使用,所以只有它的副作用,并且常量expression式有副作用是没有意义的。
由于variables是自动的,因此编译器不会将其视为常量expression式。 允许在运行时进行评估并获得价值。 尝试使variables静态,你会看到相同的错误消息,因为编译器将需要一个常量expression式的时间。
gcс接受这个:
int a = (10,20) ; int main() { printf("%d\n",a); }
并打印20
。 可能这是你的编译器的问题?