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

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。很明显,事实并非如此。

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

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


当前回答

你的问题唯一正确的答案是:因为它是没有定义的。

我+ = + +;结果0是未定义的。

如果你愿意的话,语言评估机制中的一个bug。甚至更糟!设计中的bug。

想要证明吗?你当然想!

int t = 0;int i = 0;t + = + +;/ / t = 0;i = 1

现在这…是直观的结果!因为我们首先对t求值并赋值只有在求值和赋值之后我们才进行后期操作,不是很合理吗?

i=i++和i=i对i产生相同的结果是合理的吗?

而t=i++和t=i对于i有不同的结果。

post操作应该发生在语句求值之后。 因此:

int i=0;
i+=i++;

应该是一样的,如果我们写

int i=0;
i = i + i ++;

因此和:

int i=0;
i= i + i;
i ++;

因此和:

int i=0;
i = i + i;
i = i + 1;

如果我们理性思考,任何不是1的结果都表明编译器中的错误或语言设计中的错误-然而MSDN和许多其他来源告诉我们“嘿,这是未定义的!”

现在,在我继续之前,即使我给出的这组例子也没有得到任何人的支持或承认。然而,这是根据直觉和理性的方式应该得到的结果。

编码器不应该知道程序集是如何编写或翻译的!

如果它以一种不尊重语言定义的方式编写——这是一个bug!

And to finish I copied this from Wikipedia, Increment and decrement operators : Since the increment/decrement operator modifies its operand, use of such an operand more than once within the same expression can produce undefined results. For example, in expressions such as x − ++x, it is not clear in what sequence the subtraction and increment operators should be performed. Situations like this are made even worse when optimizations are applied by the compiler, which could result in the order of execution of the operations to be different than what the programmer intended.

因此。

正确的答案是不应该使用!(因为它没有定义!)

是的. .-它有不可预测的结果,即使c#编译器试图以某种方式规范化它。

我没有找到任何关于c#的文档,把你们所有人都记录下来的行为描述为一种正常的或定义良好的语言行为。但我的发现恰恰相反!

[从MSDN文档中复制后缀自增和自减操作符:++和——]

当后缀操作符应用于函数实参时,不保证实参的值在传递给函数之前是递增或递减的。有关更多信息,请参阅c++标准中的1.9.17节。

注意这些话并不能保证……

其他回答

因为i++首先返回值,然后对其递增。但是当i被设为1后,你把它设回0。

I += I ++;Will等于0,因为它在后面执行++。

I += ++ I;之前会做

有两种选择:

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

i++;
i+=i;

那么结果是2。

For

else if
i+=0;
i++;

结果是1。

上面的答案有很多很好的推理,我只是做了一个小测试,想和你分享

int i = 0;
i+ = i++;

这里result i显示0 result。 现在考虑以下情况:

案例1:

i = i++ + i; //Answer 1

之前我认为上面的代码类似于这个,所以第一眼看答案是1,而这个I的真正答案是1。

案例2:

i = i + i++; //Answer 0 this resembles the question code.

这里的增量操作符没有出现在执行路径中,不像前面的情况,i++有机会在加法之前执行。

我希望这对你有所帮助。谢谢

运行代码的反汇编:

int i = 0;
  xor         edx, edx
  mov         dword ptr i, edx         // set i = 0
i += i++;
  mov         eax, dword ptr i         // set eax = i (=0)
  mov         dword ptr tempVar1, eax  // set tempVar1 = eax (=0)
  mov         eax, dword ptr i         // set eax = 0 ( again... why??? =\ )
  mov         dword ptr tempVar2, eax  // set tempVar2 = eax (=0)
  inc         dword ptr i              // set i = i+1 (=1)
  mov         eax, dword ptr tempVar1  // set eax = tempVar1 (=0)
  add         eax, dword ptr tempVar2  // set eax = eax+tempVar2 (=0)
  mov         dword ptr i, eax         // set i = eax (=0)

等价的代码

它编译成与下面代码相同的代码:

int i, tempVar1, tempVar2;
i = 0;
tempVar1 = i; // created due to postfix ++ operator
tempVar2 = i; // created due to += operator
++i;
i = tempVar1 + tempVar2;

分解第二个代码(只是为了证明它们是相同的)

int i, tempVar1, tempVar2;
i = 0;
    xor         edx, edx
    mov         dword ptr i, edx
tempVar1 = i; // created due to postfix ++ operator
    mov         eax, dword ptr i
    mov         dword ptr tempVar1, eax
tempVar2 = i; // created due to += operator
    mov         eax, dword ptr i
    mov         dword ptr tempVar2, eax
++i;
    inc         dword ptr i
i = tempVar1 + tempVar2;
    mov         eax, dword ptr tempVar1
    add         eax, dword ptr tempVar2
    mov         dword ptr i, eax

打开拆卸窗口

大多数人不知道,甚至不记得,他们可以使用Visual Studio反汇编窗口看到最终的内存汇编代码。它显示的是正在执行的机器代码,而不是CIL。

在调试时使用这个:

调试(菜单)-> Windows(子菜单)->拆卸

那么后缀++发生了什么?

后缀++表示我们想在求值…之后增加操作数的值。每个人都知道……让人有点困惑的是“评估之后”的含义。

那么“评估之后”是什么意思呢?

操作数在同一行代码上的其他用法必须受到影响: A = i++ + i,第二个i受增量影响 Func(i++, i)第二个i受到影响 在同一行中的其他用法是关于短路运算符的,如||和&&: (false && i++ != i) || i == 0第三个i不受i++的影响,因为它没有被计算

那么i+ = i++;是什么意思呢?

这和i = i+ i++;

求值顺序为:

存储i + i(即0 + 0) 增量i (i变成1) 将步骤1的值赋给i (i变为0)

并不是说增量被丢弃了。

i = i++ + i;是什么意思?

这与前面的例子不同。第三个i受到增量的影响。

求值顺序为:

存储i(那是0) 增量i (i变成1) 存储步骤1 + i的值(即0 + 1) 将第3步的值赋给i (i变成1)