C 逗号运算符
Posted
技术标签:
【中文标题】C 逗号运算符【英文标题】:C comma operator 【发布时间】:2010-12-16 19:05:41 【问题描述】:为什么在逗号运算符中指定的表达式(如下例)不被视为常量表达式?
例如,
int a = (10,20) ;
当在全局范围内给出时会产生错误“初始化程序不是常量”,尽管由逗号运算符分隔的两个表达式都是常量(常量表达式)。为什么整个表达式不被视为常量表达式?为澄清起见,我已阅读 What does the ‘,’ operator do in C? 和 Uses of C comma operator。他们没有处理逗号运算符的这方面。
【问题讨论】:
谢谢罗塞尔。现在文本具有更高的可读性。 What does the comma operator `,` do in C? 的可能副本 【参考方案1】:ISO C99 标准的6.6/3
部分“常量表达式”是您需要的部分。它指出:
常量表达式不应包含赋值、递增、递减、函数调用、 或逗号运算符,除非它们包含在不属于 评估。
在 ISO 的 C99 基本原理文档中,有这个小 sn-p:
整数常量表达式必须只包含在翻译时已知的数字,以及没有副作用的运算符。
而且,如果您不依赖副作用,则使用逗号运算符 根本没有意义,因此它在常量表达式中毫无用处。
我的意思是这两个代码段之间绝对没有区别:
while (10, 1) ...
while (1) ...
因为10
实际上并没有做 任何事情。事实上,
10;
是一个完全有效但不是很有用的 C 语句,大多数人在更好地了解该语言之前都无法理解。
但是,这两种说法之间有的区别:
while ( 10, 1) ...
while (x=10, 1) ...
后面使用逗号操作符有一个副作用,就是将变量x
设置为10
。
至于为什么它们不喜欢常量表达式中的副作用,常量表达式的全部意义在于它们可以在编译时评估而不需要执行环境 - ISO 对翻译(编译时)进行了区分和执行(运行时)环境。
关于为什么 ISO 决定不要求编译器提供执行环境信息(除了包含在诸如 limits.h
之类的头文件中的内容)的线索可以稍后在基本原理文档中找到:
然而,虽然实现当然可以在翻译和执行环境中产生完全相同的结果,但这被认为是许多交叉编译器无法忍受的负担。
换句话说,ISO 不希望交叉编译器的制造商为每个可能的目标提供执行环境。
【讨论】:
+1:我只是在找这个。我相信更深层次的原因是逗号运算符引入了一个序列点。 感谢 paxdiablo。我需要参考理由文件来消除我的疑问。【参考方案2】:编译器不会将其视为常量表达式,因为变量是自动的。它允许在运行时被评估并获得一个值。尝试将变量设为静态,您将看到与编译器需要常量表达式相同的错误消息。
【讨论】:
【参考方案3】:ISO/IEC 9899:1999 6.6/3(常量表达式)规定常量表达式不得包含逗号运算符(除非未计算的子表达式的一部分),因此(10,20)
不是常量表达式定义。
理由必须是因为逗号表达式的第一部分的值不是使用它只是为了它的副作用,并且常量表达式有副作用是没有意义的。
【讨论】:
【参考方案4】:gcс 接受这个:
int a = (10,20) ;
int main()
printf("%d\n",a);
并打印20
。可能是你的编译器的问题?
【讨论】:
哪个版本的 GCC 在哪个平台上带有哪个标志?我在没有标志的 MacOS X 10.5.8 上尝试使用 GCC 4.0.1 并得到错误。 gcc 版本 3.4.4(cygming 特殊,gdc 0.12,使用 dmd 0.125)Cygwin,没有标志。 @egorius 尝试使用开关 -pedantic以上是关于C 逗号运算符的主要内容,如果未能解决你的问题,请参考以下文章