我正在將C++實用程序移植到C#。當我用C++運行下面的語句時,我得到了正確的操作。當我在C#中運行相同的語句,但是......C#的操作員的操作順序
有誰知道爲什麼「開頭++」執行?瘋狂的事情是,如果我運行(i%2)== 0與i = 0,立即窗口返回true。
我正在將C++實用程序移植到C#。當我用C++運行下面的語句時,我得到了正確的操作。當我在C#中運行相同的語句,但是......C#的操作員的操作順序
有誰知道爲什麼「開頭++」執行?瘋狂的事情是,如果我運行(i%2)== 0與i = 0,立即窗口返回true。
運算符優先級在這個問題中是無關緊要的。這是導致此行爲的評估順序。
在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++中是未定義的,只是碰巧工作。
在此基礎上,你可以改變它爲'buffer [i] =(i ++%2)== 0? temp [end--]:temp [begin ++];' – Rob
@Rob雖然這會工作,但它仍然是可怕的代碼。 – CodesInChaos
啊我看到了,謝謝你的解釋(和鏈接)。 – tlg
我不知道,但你爲什麼不直接明確你的意圖?
if(i % 2 == 0) {
buffer[i] = temp[end--];
} else {
buffer[i] = temp[begin++];
}
i++;
我甚至會在if後加上i ++。而較高的運算符優先級意味着較早的執行是一個常見的神話。 – CodesInChaos
我想我會介紹一個溫度,並避免兩次寫入緩衝[i ++]。但是,是的,這是處理這個問題的正確方法。事實上,我沒有問題在單獨的行上寫增量,當這樣做時沒有參數。 –
@CodeInChaos:你說得對,編輯過。 – Ryan
你確定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
有奇數個元素。
這是甚至在C++中定義的行爲? – CodesInChaos
哪個是哪個? –
如果這不能說服你停止編寫這樣的代碼,我不知道會發生什麼。 –