首先,亨克和奥利维尔的答案是正确的。我想用稍微不同的方式来解释它。具体来说,我想解决您提出的这一点。您具有以下一组语句:
int k = 10;
int c = 30;
k += c += k += c;
然后,您错误地得出结论,这应该产生与以下语句集相同的结果:
int k = 10;
int c = 30;
k += c;
c += k;
k += c;
查看您如何弄错了以及如何正确做对很有帮助。分解它的正确方法是这样的。
首先,重写最外面的+ =
k = k + (c += k += c);
其次,重写最外面的+。 我希望您同意x = y + z必须始终与“将y评估为临时值,将z评估为临时值,将临时项求和,将总和分配给x”相同。因此,让我们明确一点:
int t1 = k;
int t2 = (c += k += c);
k = t1 + t2;
确保清楚,因为这是您错了的步骤。将复杂的操作分解为更简单的操作时,必须确保缓慢而谨慎地进行操作,并且不要跳过步骤。跳过步骤是我们犯错的地方。
好的,现在,再次缓慢而仔细地将任务分配到t2。
int t1 = k;
int t2 = (c = c + (k += c));
k = t1 + t2;
分配将向t2分配与分配给c相同的值,所以说:
int t1 = k;
int t2 = c + (k += c);
c = t2;
k = t1 + t2;
大。现在分解第二行:
int t1 = k;
int t3 = c;
int t4 = (k += c);
int t2 = t3 + t4;
c = t2;
k = t1 + t2;
太好了,我们正在进步。将任务分解为t4:
int t1 = k;
int t3 = c;
int t4 = (k = k + c);
int t2 = t3 + t4;
c = t2;
k = t1 + t2;
现在分解第三行:
int t1 = k;
int t3 = c;
int t4 = k + c;
k = t4;
int t2 = t3 + t4;
c = t2;
k = t1 + t2;
现在,我们可以看整个事情:
int k = 10; // 10
int c = 30; // 30
int t1 = k; // 10
int t3 = c; // 30
int t4 = k + c; // 40
k = t4; // 40
int t2 = t3 + t4; // 70
c = t2; // 70
k = t1 + t2; // 80
因此,完成后,k为80,c为70。
现在让我们看一下如何在IL中实现这一点:
int t1 = k;
int t3 = c;
is implemented as
ldloc.0 // stack slot 1 is t1
ldloc.1 // stack slot 2 is t3
现在这有点棘手:
int t4 = k + c;
k = t4;
is implemented as
ldloc.0 // load k
ldloc.1 // load c
add // sum them to stack slot 3
dup // t4 is stack slot 3, and is now equal to the sum
stloc.0 // k is now also equal to the sum
我们本可以实现为
ldloc.0 // load k
ldloc.1 // load c
add // sum them
stloc.0 // k is now equal to the sum
ldloc.0 // t4 is now equal to k
但是我们使用了“ dup”技巧,因为它可以使代码更短并使抖动更容易,并且得到相同的结果。 通常,C#代码生成器会尝试将临时“临时”尽可能多地保留在堆栈上。如果你发现它更容易跟随IL用更少的短命,把优化关闭,代码生成器就会较少攻击性。
现在,我们必须做同样的技巧才能得到c:
int t2 = t3 + t4; // 70
c = t2; // 70
is implemented as:
add // t3 and t4 are the top of the stack.
dup
stloc.1 // again, we do the dup trick to get the sum in
// both c and t2, which is stack slot 2.
最后:
k = t1 + t2;
is implemented as
add // stack slots 1 and 2 are t1 and t2.
stloc.0 // Store the sum to k.
由于我们不需要这笔总和,因此我们不会将其重复。堆栈现在是空的,我们在语句的结尾。
这个故事的寓意是:当您试图理解一个复杂的程序时,总是一次分解一个操作。不要捷径;他们会让你误入歧途。