x = x++ + ++x; 的求值顺序是什么?

8

重复问题:https://dev59.com/L3NA5IYBdhLWcg3wdtv5 http://stackoverflow.com/questions/1826414/whats-the-value-of-i-i-closed https://dev59.com/mUrSa4cB1Zd3GeqPWnqW - bk1e
18
lol。mod封锁了自己的问题:D。 - Earlz
3
谢谢提供链接。我感觉以前可能已经涉及到这个问题,但当我问的时候没有出现。我想找到原始信息最快的方法就是直接询问。 :) - Bill the Lizard
11
@Earlz:一旦有人指出这是重复的,我就必须这样做。我不能因为这是我的问题而让它保持开放状态,这样做是不正确的。 :) - Bill the Lizard
@Prasoon:我希望如此! :) - John Knoeller
4个回答

14

+运算符中的参数求值顺序是未指定的 - 但这并不重要,因为在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 的输出。


4

C++03标准5.4节

除非有特别说明,否则单个操作符和子表达式的操作数以及单个表达式的副作用发生的顺序均未指定。53)在前一序列点和后一序列点之间,标量对象的存储值应通过表达式的计算最多被修改一次。此外,先前的值仅用于确定要存储的值。对于一个完整表达式的子表达式的任何允许顺序,都必须满足本段所述的要求;否则行为是未定义的。

...... 因此,是未定义和实现相关的。


3

C标准不能保证后置自增在前置自增之后“发生”,因此这是未定义行为。


2

这不是一个有效的C语句,因此谈论其评估顺序是没有意义的。


1
“valid”是什么意思?它在gcc和g++中成功编译。 - nobody
4
文件是否能够被gcc成功编译与其是否包含有效的C语句无关。什么是有效的C语言由C标准定义,而不是由单个编译器决定。 - Stephen Canon
4
这个语句在语法上是合法的,但在语义上是不正确的,因为它会导致未定义的行为。 - qrdl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接