2010-12-12 195 views
8

我有这个代码后增量问题

static void Main(string[] args) 
{ 
    int x = 20; 
    int y = 35; 
    x = y++ + x++; 
    y = ++y + ++x; 
    Console.WriteLine(x); 
    Console.WriteLine(y); 
    Console.ReadLine(); 
} 

我预计输出为x = 57和y = 94。然而,在执行时它给了我56和93 出于某种原因后增量运算符没有在第3行执行。

这是因为我们将第3行中的表达式的结果赋值给x本身?是否还有其他情况下,后增量运算符不会按预期结果。

谢谢。

+3

只是一个提示:如果你把每个测试用例放在一个单独的函数中,这样的情况就容易得多了。由于第一次分配,验证第二次分配中发生的事情是非常困难的。 – 2010-12-12 11:02:22

回答

13
int x = 20; 
int y = 35; 
// x = y++ + x++; this is equivalent of 
tmp = 35 + 20; y++; x++; x = tmp; 
// so here we have x = 55; y = 36 
// y = ++y + ++x; 
y ++; // 37 
x ++; // 56; 
y = x + y; 
// so here we have y = 93, x = 56; 
+0

谢谢 - 这清除了我的怀疑。 – stackoverflow 2010-12-12 11:11:07

3

执行顺序由运算符优先级和关联性决定。

分配是右结合的,所以

x = y + x++; 

可以改写

t = y + x++; 
x = t; 

我无法找到该++=之前发生的其实是一个很明确的说法。
但Ecma文件§ 14.2中的文字暗示副作用是作为评估i++本身的一部分而发生的。在F(i) + G(i++) * H(i)中,用新值i调用H(i)

+0

但请注意,_evaluation_的顺序不必执行_execution_的特定顺序。 – SoftMemes 2010-12-12 12:05:14

+0

@Freed是正确的。操作符*的执行顺序*由优先级和关联性决定。 *次表达*的评估顺序始终保持在正确的位置。 – 2010-12-12 15:29:04

+2

我还注意到,如果“x”是一个带有副作用的表达式,那么您关于作业的声明不正确。例如:M()。x = y + N()。x ++不同于t = y + N()。 M()。x = t;因为这颠倒了M和N被调用的顺序。 – 2010-12-12 15:31:09

9

C#中的规则非常简单。它们是:

  • 表达式的子表达式被评估左边到右边,期间,结尾的故事。
  • 增量操作符的副作用发生在操作符被评估时。

所以在你的情况下,这样就崩溃了;我会假装我们用C而不是C#来完成这个工作,所以地址和解除引用更清晰。

x = y++ + x++; 

评估x的地址并存储它。

t1 = &x; 

评估y的地址。

t2 = &y; 

评估存储在刚刚计算的地址中的值。那是35.

t3 = *t2; // 35 

刚刚计算的值是表达式的值;它是之前的值的增量。

添加一个该值。

t4 = t3 + 1; // 36 

在地址中存储36。你现在36岁。

*t2 = t4; // y = 36 

现在做同样的X ++:

t5 = &x; 
t6 = *t5;  // 20 
t7 = t6 + 1; // 21 
*t5 = t7;  // x = 21 

OK,现在我们要做加法:

t8 = t3 + t6; // 35 + 20 = 55 

,并分配到第一计算的地址:

*t1 = t8; // x = 55; 

在本声明的末尾x有有三个价值观。 20,21和55 Y已有两个值,35和36位x现在是55,现在y是36

y = ++y + ++x; 

现在,我们再次做同样的事情,只不过这次我们使用的值后,增量。被这句话Y的有三个值结束

t1 = &y; 
t2 = &y; 
t3 = *t2; // 36 
t4 = t3 + 1; // 37 
*t2 = t4; // y = 37; 
t5 = &x; 
t6 = *t5; // 55 
t7 = t6 + 1; // 56; 
*t5 = t7; // x = 56; 
t8 = t4 + t7; // 93 
*t1 = t8; // y = 93; 

所以:36,37和93 X已经有两个值:跟着现在55和56 y是93,x是现在56

我预计输出为x = 57和y = 94

你为什么想到?您的期望与C#规范相反;我很想知道你为什么期望得到错误的结果。您是如何期望生成此代码的?您是否期望之后的增量在之后发生?他们为什么要那样做? 当增量运算符的值被评估为时,发生增量,并且明显必须在之前发生加法,这显然必须在赋值之前发生。所以后的增量不会发生的赋值。

出于某种原因后增量运算符不符合3

如何在地球上,你得出这个结论得到执行?我向你保证它肯定正在执行中。如果你不相信我,请在调试器中执行。

+0

1+,从马口... – SoftMemes 2010-12-12 21:56:09

+0

感谢您的详细回复..我们对后增量的理解是错误的。 x = y ++ + x ++;对我们而言意味着x = y + x; y = y + 1; x = x + 1;这样我们到了20 + 35; 35 + 1; 55 + 1;并且由于最后一个表达式在x上,我们假定它是56。 – stackoverflow 2010-12-13 15:22:08