在Java中,求值顺序被指定为从左到右。C和C++是否也是如此,还是与实现有关?我记得函数参数的求值顺序是未指定的,但子表达式呢?
可能是重复问题:Could anyone explain these undefined behaviors (i = i++ + ++i , i = i++, etc…)
可能是重复问题:Could anyone explain these undefined behaviors (i = i++ + ++i , i = i++, etc…)
+
运算符中的参数求值顺序是未指定的 - 但这并不重要,因为在C和C++中,未经过中间序列点(intervening sequence point)修改同一对象两次或以上是完全未定义的行为。
在这里,您在未经过中间序列点的情况下修改x
三次,所以您已经进入了未知领域。 ;)
C99标准中相关的部分是"6.5表达式":
2 在前一个和后一个序列点之间, 通过对一个表达式的求值最多只能对一个对象进行存储值的修改。 此外,读取先前的值仅用于确定要存储的值。
以及
3 运算符和操作数的分组由语法指示。 除非稍后指定(对于函数调用(), &&, ||, ?:和逗号运算符),否则子表达式的求值顺序和副作用发生的顺序都是未指定的。
可以编写合法的代码来演示未指定的求值顺序 - 例如:
#include <stdio.h>
int foo(void)
{
puts("foo");
return 1;
}
int bar(void)
{
puts("bar");
return 2;
}
int main()
{
int x;
x = foo() + bar();
putchar('\n');
return x;
}
无法确定您将获得 foobar
还是 barfoo
的输出。
C++03标准5.4节
除非有特别说明,否则单个操作符和子表达式的操作数以及单个表达式的副作用发生的顺序均未指定。53)在前一序列点和后一序列点之间,标量对象的存储值应通过表达式的计算最多被修改一次。此外,先前的值仅用于确定要存储的值。对于一个完整表达式的子表达式的任何允许顺序,都必须满足本段所述的要求;否则行为是未定义的。
...... 因此,是未定义和实现相关的。
C标准不能保证后置自增在前置自增之后“发生”,因此这是未定义行为。
这不是一个有效的C语句,因此谈论其评估顺序是没有意义的。