2011-11-20 173 views
0

我正在將C++實用程序移植到C#。當我用C++運行下面的語句時,我得到了正確的操作。當我在C#中運行相同的語句,但是......C#的操作員的操作順序

omgwtfbbq

有誰知道爲什麼「開頭++」執行?瘋狂的事情是,如果我運行(i%2)== 0與i = 0,立即窗口返回true。

+4

這是甚至在C++中定義的行爲? – CodesInChaos

+0

哪個是哪個? –

+8

如果這不能說服你停止編寫這樣的代碼,我不知道會發生什麼。 –

回答

12

運算符優先級在這個問題中是無關緊要的。這是導致此行爲的評估順序。

在C#i++之前評估i % 2,因爲它在左側。因此i % 2是錯誤的,並且if的右側被評估。

首先使用優先得到語法樹:

= 
    buffer[i++] 
    if i % 2 
    then temp[end--] 
    else temp[begin++] 

在從左至右你評估孩子的每個節點。這意味着i++i % 2之前被評估。

埃裏克利珀有大量的對這個職位的,都在這裏對SO,並在自己的博客:

個人而言,我會避免這樣的代碼。這是好得多把它分割成多個表情,甚至使用普通的if聲明,而不是? :


在C++中訪問這是兩者之間是不確定的行爲寫入沒有序列點的變量。我認爲=不是序列點,所以我猜你的表達式在C++中是未定義的,只是碰巧工作。

+1

在此基礎上,你可以改變它爲'buffer [i] =(i ++%2)== 0? temp [end--]:temp [begin ++];' – Rob

+3

@Rob雖然這會工作,但它仍然是可怕的代碼。 – CodesInChaos

+0

啊我看到了,謝謝你的解釋(和鏈接)。 – tlg

3

我不知道,但你爲什麼不直接明確你的意圖?

if(i % 2 == 0) { 
    buffer[i] = temp[end--]; 
} else { 
    buffer[i] = temp[begin++]; 
} 

i++; 
+0

我甚至會在if後加上i ++。而較高的運算符優先級意味着較早的執行是一個常見的神話。 – CodesInChaos

+0

我想我會介紹一個溫度,並避免兩次寫入緩衝[i ++]。但是,是的,這是處理這個問題的正確方法。事實上,我沒有問題在單獨的行上寫增量,當這樣做時沒有參數。 –

+0

@CodeInChaos:你說得對,編輯過。 – Ryan

0

你確定begin < end是正確的?如果我沒有弄錯,你會錯過最後一個元素。

這是我會怎麼寫C++:

for (; begin <= end; ++i) 
{ 
    buffer[i] = temp[(i & 1) == 0 ? end-- : begin++]; 
} 

但是,如果你仔細想想,在循環內的條件真的是沒有必要的,因爲它的觸發器與每一個迭代。這將是更有效的方法簡單地有兩個複製操作的循環中:

while (begin < end) 
{ 
    buffer[i++] = temp[end--]; 
    buffer[i++] = temp[begin++]; 
} 
if (begin == end) 
{ 
    buffer[i++] = temp[end--]; 
} 

我改變循環條件回<和的情況下添加一個if有奇數個元素。