一尘不染

对于i = 0,为什么(i + = i ++)等于0?

c#

采用以下代码(可用作控制台应用程序):

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

结果i为0。我期望为2(就像我的一些同事一样)。编译器可能会创建某种导致i零的结构。

我期望2的原因是,按照我的观点,将首先评估右手陈述,将i加1。然后将其加到i。因为我已经是1,所以它将1加1。所以1 + 1
=2。显然,这不是正在发生的事情。

您能解释一下编译器做什么或在运行时发生什么吗?为什么结果为零?

免责声明:我绝对知道您不会(也许不应该)使用此代码。 我知道我永远不会。不过,我发现知道为什么以这种方式起作用以及正在发生的事情很有趣。


阅读 1145

收藏
2020-05-19

共1个答案

一尘不染

这个:

int i = 0;
i += i++

可以在您做的时候看到(以下是过于简化的情况):

int i = 0;
i = i + i; // i=0 because the ++ is a postfix operator and hasn't been executed
i + 1; // Note that you are discarding the calculation result

实际发生的事情比这还涉及更多-看一下MSDN,7.5.9 Postfix递增和递减运算符

x ++或x–形式的后缀递增或递减操作的运行时处理包括以下步骤:

  • 如果x被分类为变量:

    • 计算x以产生变量。
    • x的值被保存。
    • 使用保存的x值作为参数调用选定的运算符。
    • 操作员返回的值存储在x的求值给出的位置。
    • x的保存值成为运算结果。

请注意,由于优先顺序的原因,后缀++发生 在之前 +=,但是结果最终未使用(因为使用了的先前值i)。


更透彻的分解,i += i++它是由零件都需要一个人知道这两个+=++不是原子(即,没有一个是单人操作),即使它们看起来像他们。这些实现的方式涉及临时变量,i即操作发生之前的副本-
每个操作一个。(我将使用的名称iAddiAssign所使用的临时变量+++=分别)。

因此,更接近发生的事情是:

int i = 0;
int iAdd = i; // Copy of the current value of i, for ++
int iAssign = i; // Copy of the current value of i, for +=

i = i + 1; // i++ - Happens before += due to order of precedence
i = iAdd + iAssign;
2020-05-19