表达式求值顺序不同于运算结合性和优先级。下面是一个经典例子,被 ISO C99/ C++98 /03 三大标准明确提到:他的结果是不确定(unspecified) 的。
i = ++i + 1; // The behavior is unspecified
在介绍概念之前,我们先解释一下它的结果。这个表达式( expression )包含3个子表达式( subexpression ):
e1 = ++i
e2 = e1 + 1
i = e2
这三个子表达式都没有顺序点( sequence point ),而 ++ i 和 i = e3 都是有副作用( side effect )的表达式。由于没有顺序点,语言不保证这两个副作用的顺序。
更加可怕的是,如果i 是一个内建类型,并在下一个顺序点之前被改写超过一次,那么结果是未定义(undefined)的!比如本例中如果有:
int i = 0x1000fffe;
i = ++i + 1; // The result is undefined!!
你也许会认为他的结果是加1 或者加2,其实更糟糕 —— 结果可能是 0x1001ffff 。他的高字节接受了一个副作用的内容,而低字节则接受了另一个副作用的内容! 如果i 是指针,那么将很容易造成程序崩溃。
为什么要这么做呢?因为对于编译器提供商来说,未确定的顺序对优化有相当重要的作用。比如,一个常见的优化策略是“减少寄存器占用和临时对象”。编译器可以重新组织表达式的求值,以便尽量不使用额外的寄存器以及临时变量。 更加严格的说,即使是编译器提供商也无法完全彻底序列化指令(比如无法严格规定读和写的顺序),因为CPU本身有权利修改指令顺序&#x