我的一些同事今天进行了辩论,我想澄清一下。它是关于表达式中的评估顺序和序列点。标准中明确指出,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清楚地警告了增量前后序列点。
答案 0 :(得分:5)
让我们看看标准中关于排序的内容:
C ++ 11 5.17 / 1:在右和左操作数的值计算之后,以及赋值表达式的值计算之前,对赋值进行排序。
因此,对操作数array[x]
和++x
的评估是不相对于彼此进行排序。两者都使用x
的值,并且一个修改它,给出未定义的行为。
(第二个例子的不同之处在于左操作数中没有使用x
的值;它仍然是左值)。
答案 1 :(得分:0)
在array[x] = ++x;
中,标量对象x
上有两个值计算,x
有一个副作用。
++x
的值计算相对于其副作用进行了排序,但x
中array[x]
的值计算相对于++x
的副作用没有排序
所以行为未定义。
x = ++x
和array[x] = ++x
之间的区别在于,前者LHS上x
的出现会产生副作用,而后者x
上出现{{1}} LHS受价值计算的影响。