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