2

所以我遇到了quora文章中的這段代碼來交換兩個數字。什麼時候賦值運算符在c中用括號中的括號括起來?

a = a + b - (b = a); 

我試過了,它工作正常。但是由於b = a在括號中不應該賦值爲第一個值嗎?整個事情應該成爲a + a - a使a保持其價值?

我試過a = b + (b = a);a = 5 b = 10,最後我得到了= 10。看到這裏我想它評估爲a = a + a

爲什麼這個異常?

+0

括號改變它們包含的運算符的優先級;他們不會改變操作的順序。 – geoffspear

+1

'UB' = [未定義的行爲](http://en.wikipedia.org/wiki/Undefined_behavior) –

+0

我試過了,它以這種方式出現,ergo它總是會以這種方式出現是最糟糕的編程的根源罪惡。 – mattnz

回答

-1

正如評論中所述,這是未定義的行爲。代碼直接從左到右讀取,而不是使用PEMDAS。

+4

PEMDAS與UB無關 – aaronman

+0

-1:代碼可能從左到右讀取,而不是由編譯器,它可以在標準的定義範圍內自由地做它想做的事情。 – mattnz

4

這是因爲從C99 draft standard6.5.2的未定義的行爲的規定:

之前和下一序列點之間的對象應當通過expression.72的評價已修改至多一次其存儲的值)此外,前一個值是隻讀以確定該值將被存儲

在這種情況下,我們正在修改b以及使用它的值來確定的a結果,標準使FOLL由於實例爲未定義:

i = ++i + 1; 
a[i++] = i; 

手搖警告至少在gcc會警覺到一個問題,用-W -Wall我收到以下警告:

warning: operation on ‘b’ may be undefined [-Wsequence-point] 
+0

你會生氣,如果我只是複製粘貼標準報價到我的答案,似乎是投票的關鍵 – aaronman

+0

@aaronman我會鼓勵你下載我在我的答案中鏈接的標準草案,找到我引用的部分並嘗試首先了解它和周圍的相關部分。 –

+0

爲什麼你認爲我不明白它;) – aaronman

0

優先建立什麼樣的操作數是由哪些運營商鏈接。它不建立評估順序。

賦值運算符的優先級非常低。其結果是,沒有括號,表達

a = a + b - b = a 

將被解析爲:

(a) = (a + b - b) = (a) 

這將導致一個錯誤,因爲(A + B - b)是不是左值。所以需要圓括號以組兩個操作數ba與賦值運算符,如你原來的語句:

a = a + b - (b = a) 

但是,所有的括號是強加的分組,而不是評價的順序。

所有你可以肯定的是,每當(b = a)評價:

  1. 整個表達式的值將是a
  2. 作爲一個副作用的價值,b將被賦予的價值a

但是,當這種情況發生時,在編譯器中是不可預測的。該標準是明確的:在複雜表達式中,評估子表達式的次序和發生副作用的次序是未指定的,即與編譯器有關。該標準對子表達式的評估順序沒有任何要求。更一般地說,在C語言中,如果在表達式的其他地方使用該變量修改變量的值,則得到的結果將是未定義的,這意味着可能發生任何事情。絕對不能依賴表達式​​,因爲它既修改了b的值,又在表達式的其他地方使用了值b

因此,表達式喚起了未指定的行爲(依賴於特定的評估順序)和未定義的行爲(在表達式中的其他地方使用它時修改了變量的值)。相當令人印象深刻的壯舉,當你想到它!

編輯:以上是C99的真實情況。最新的標準C11明確地調用這個行爲undefined:「如果對標量對象的副作用不是相對於同一個標量對象的不同副作用或者是使用相同標量對象的值進行值計算,那麼行爲沒有定義,如果一個表達式的子表達式有多個可允許的排序順序,那麼如果這種無序的副作用發生在任何排序中,則行爲是不確定的。 (6.5.2)。 draft standard免費提供。

相關問題