在C語言中,有你需要知道的兩個不同的問題:運算符優先級和爲了評估的。
運算符優先級決定哪個運算符獲得首先評估的操作數,以及屬於哪個運算符的哪些操作數。例如在表達式a + b * c
中,運算符*的運算符優先級高於+。因此,表達式將被評估爲
a + (b * c)
在C語言中的所有運營商有確定性優先級,他們是在任何編譯器是相同的。
評估順序決定哪個操作數首先得到評估。請注意,子表達式也是一個操作數。評估順序在運營商優先級確定後應用。如果上面的a + b * c示例具有從左到右的評估順序,則操作數本身將按照a,b,c的順序進行評估。如果操作數是例如函數調用,那麼函數a(),b()和c()將按照該順序執行。這個例子中的所有操作數都需要被評估,因爲它們都被使用了。如果編譯器可以確定某些操作數不需要進行評估,則可以優化它們,而不管這些操作數是否包含副作用(如函數調用)。
的問題是操作數的計算順序是最常見的不確定的行爲,這意味着編譯器是免費的評估是左到右或從右到左,我們無法知道或承擔任何事它。對於C中的大多數操作數來說,這是事實,除了評估順序始終是確定性的一些例外。這些是運營商|| && ?: ,
的操作數,其中評估的順序保證爲從左到右。 (當使用正規的C語言的語義,一個說有左的評價和右操作間的時序點。)
所以對於具體的例子m = ++i || ++j && ++k
。
- 一元前綴++運算符的優先級最高,它們將運算符i,j和k綁定到它們。這個語法非常直觀。
- 二進制& &運算符具有第二高的優先級,將運算符
++j
和++k
綁定到它。所以表達式相當於m = ++i || (++j && ++k)
。
- 二進制||運營商具有第三高優先級,將運營商
i++
和(j++ && ++k)=
綁定到它。
- 賦值操作符=具有最低的優先級,結合運營商
m
和++i || (++j && ++k)
到它。
此外,我們可以看到,無論是||並且運營商是保證評估順序保持從左到右的那些運營商之一。換句話說,如果||的左操作數運算符被評估爲true,編譯器不需要評估正確的操作數。在具體的例子,++i
總是正的,所以編譯器可以執行相當的優化,有效地改造了表達m = ++i;
如果i
值在編譯時不知道,編譯器會被強行評估整個表達。然後表達式將按此順序進行了評價:
- & &比||優先級高,所以開始評估& &操作。
- & &操作者保證具有左到右操作數的評價順序,因此首先執行++Ĵ。
- 如果++ j的結果爲真(大於零),並且只有這樣,則評估正確的運算符:perform ++ k。
- 商店++Ĵ& & ++ K的臨時變量的結果。我在這裏將其稱爲
j_and_k
。如果++ j和++ k都爲正,則j_and_k
將包含值1(真),否則包含0(假)。
- ||運算符保證有操作數從左到右的評估順序,所以先執行++ i。
- 如果++ i是假(零),也只有這樣,評估右操作「
j_and_k
」。如果其中一個或兩個都是肯定的,則||的結果運算符爲1(真),否則爲0(假)。
- m取決於結果獲取值1或0。
哦,不,不會再 –
這是一個常見的問題功課這些天? – crashmstr