下面的代码(可用作控制台应用程序):

static void Main(string[] args)
{
    int i = 0;
    i += i++;
    Console.WriteLine(i);
    Console.ReadLine();
}

i的结果是0。我以为会有2个(和我的一些同事一样)。可能编译器创建了某种结构,导致i为零。

我期望2的原因是,在我的思路中,右边的语句会先求值,使I加1。然后加上i,因为i已经是1了,所以是1加1。所以1 + 1 = 2。很明显,事实并非如此。

你能解释编译器做什么或者在运行时发生了什么吗?为什么结果是零?

某种免责声明:我非常清楚您不会(而且可能不应该)使用此代码。我知道我永远不会。尽管如此,我觉得了解它为什么会以这样的方式工作以及究竟发生了什么是很有趣的。


当前回答

简单地说,

i++,将在“+=”运算符完成后给“I”加1。

你想要的是++i,这样它就会在“+=”运算符执行之前给“i”加1。

其他回答

后修正自增操作符++,在表达式中给变量一个值,然后对i再次执行你分配的返回0(0)值的自增操作,这将覆盖增加的1(1),所以你得到0。您可以在++ operator (MSDN)中阅读更多关于自增操作符的信息。

有两种选择:

第一个选项:如果编译器按如下方式读取语句,

i++;
i+=i;

那么结果是2。

For

else if
i+=0;
i++;

结果是1。

变量后面的++操作符使其成为后加式。增量操作发生在语句中的其他所有操作之后,包括加法和赋值操作。相反,如果你把++放在变量之前,它会在i的值被计算之前发生,并给你预期的答案。

这只是从左到右、自底向上的抽象语法树的计算。从概念上讲,表达式的树是从上到下遍历的,但是当递归从树的底部弹出时,计算就展开了。

// source code
i += i++;

// abstract syntax tree

     +=
    /  \
   i    ++ (post)
         \
         i

计算从考虑根节点+=开始。这是这个表达式的主要组成部分。必须计算+=的左操作数,以确定存储变量的位置,并获得前值为零。接下来,右边必须求值。

右边是一个后递增的++操作符。它有一个操作数i,它既作为值的来源,也作为值的存储位置进行计算。运算符对i求值,找到0,然后将1存储到该位置。它根据返回先验值的语义返回先验值0。

现在控制回到+=运算符。现在它有了完成操作的所有信息。它知道存储结果的位置(i的存储位置)以及先前的值,并且它有要添加到先前值的值,即0。所以i最后是0。

像Java一样,c#通过固定求值顺序,清除了C语言中一个非常愚蠢的方面。从左到右,自底向上:程序员可能期望的最明显的顺序。

i++的意思是:返回i的值,然后增加它。

I += i++表示: 取i的当前值。 添加i++的结果。

现在,让我们加入i = 0作为起始条件。 I += i++现在是这样计算的:

i的当前值是多少?它是0。存储它,这样我们就可以将i++的结果添加到它。 Evaluate i++(求值为0,因为这是i的当前值) 加载存储值并将第2步的结果添加到其中。(0加0)

注意:在第2步结束时,i的值实际上是1。但是,在第3步中,通过在i的值增加之前加载它来丢弃它。

与i++不同,++i返回的是增加后的值。

因此,i+= ++i会得到1。