2010-12-12 196 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