序列点和评估顺序(预增量)

时间:2014-08-20 10:13:15

标签: c++ c++11 language-lawyer

我的一些同事今天进行了辩论,我想澄清一下。它是关于表达式中的评估顺序和序列点。标准中明确指出,C / C ++在表达式中没有从左到右的评估,这与Java之类的语言不同,后者保证具有从左到右的顺序。因此,在下面的表达式中,在评估最右边的操作数(C)之前,对二进制操作中最左边的操作数(B)的求值进行排序:

A = B B_OP C

根据序列规则(未定义行为)和Bjarne的TCPPL 3rd ed小节下的CPPReference下面的表达式是UB

x = x++ + 1;

它可以被解释为编译器,但是下面的表达式被认为是C ++ 11中明确定义的行为

x = ++x + 1;

所以,如果上面的表达式定义得很好,那么" fate"这个

array[x] = ++x;

似乎没有定义后增量和后减量的评估,但定义了预增量和预减量。

注意:这不用于实际代码。 Clang 3.4和GCC 4.8清楚地警告了增量前后序列点。

2 个答案:

答案 0 :(得分:5)

让我们看看标准中关于排序的内容:

  

C ++ 11 5.17 / 1:在右和左操作数的值计算之后,以及赋值表达式的值计算之前,对赋值进行排序。

因此,对操作数array[x]++x的评估是相对于彼此进行排序。两者都使用x的值,并且一个修改它,给出未定义的行为。

(第二个例子的不同之处在于左操作数中没有使用x的值;它仍然是左值)。

答案 1 :(得分:0)

array[x] = ++x;中,标量对象x上有两个值计算,x有一个副作用。

++x的值计算相对于其副作用进行了排序,但xarray[x]的值计算相对于++x的副作用没有排序

所以行为未定义。

x = ++xarray[x] = ++x之间的区别在于,前者LHS上x的出现会产生副作用,而后者x上出现{{1}} LHS受价值计算的影响。