本節書摘來自異步社群《c語言解惑》一書中的第1章,第1.6節,作者 傅道坤,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視
請問,下面這個程式的輸出是什麼?
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnL5YjMlF2MwQWYwgTOhN2NzQzNxcTYycDNyczYkNWMiJGNiZ2N5cjZi9CXt92Yu4GZjlGbh5SZslmZxl3Lc9CX6MHc0RHaiojIsJye.png)
輸出:
解惑1.6 操作符的優先級和求值順序
初始值:x = 1, y = 1, z = 1
++ x || ++ y && ++ z
((++ x) || ((++ y) && (++z))) 把操作數綁定到操作符上。
(2 || ((++ y) && (++z))), 此時x=2 按從左到右的順序依次求值。
(true ||任意值) 因為“||”操作符的左操作數是true,是以沒有必要繼續求值了。事實上,c語言肯定不會繼續求值——按照c語言裡的有關規則,在按從左到右的順序對一個邏輯表達式求值的時候,隻要知道了它的實際結果,就不會再對其餘部分求值。具體到這道謎題,這意味着y和z的值仍将是1。
true, 即1
++ x && ++ y || ++z
(((++ x) && (++ y))||(++z))
((true && (++ y))||(++z)), 此時x=2
((true && true)||(++z)), 此時y = 2 按從左到右的順序依次求值。
(true ||(++z))
true, 即1 變量z的值沒有發生變化。
++ x && ++ y && ++ z
(((++ x) && (++ y)) && (++z))
((2 && 2) && (++z)), 此時x = 2,y = 2
(true && (++z))
(true && true), 此時z =2
初始值:x = -1, y = -1, z = -1
++ x && ++ y || ++ z
(((++ x) && (++ y)) || (++z))
((0 && (++ y)) || (++z)), 此時x=0
((false && (++y)) || (++z))
(false || (++z)) 因為“&&”操作符的左操作數是false,是以沒有必要對++y求值。可是,“||”操作的結果現在還不能确定。
(false || (0)), 此時z = 0`
(false || false)
false, 即0
++ x||++ y && ++z
((++ x)||((++ y) && (++z)))
(false||((++ y) && (++z))), 此時x=0
(false||(false && (++z))), 此時y = 0
(false||(false)
++ x && ++ y && ++z
(((++ x) && (++ y))&&(++z))
((false && (++ y))&&(++z)), 此時x=0
(false && (++z))
關于邏輯操作符的副作用:正如你們現在已經體會到的那樣,c語言裡的邏輯表達式的求值有一定的難度,因為是否需要對邏輯操作符的右操作數求值取決于其左操作數的求值結果。這種根據具體情況來決定是否對右操作數求值的做法是邏輯操作的一個有用的屬性。可是,如果在邏輯表達式的右半部分隐藏着副作用,那麼就難免會留下隐患——那些副作用可能會發作,也可能不會發作。一般說來,謹慎對待副作用總是沒錯的,這在邏輯表達式中就更為重要了。
[1] lvalue,能夠出現在指派操作符“=”左側的記号。——譯者注
[2] 這裡所說的“副作用”是指在執行一條本身并無文法錯誤的語句時會産生的難以确定的後果。c程式的副作用幾乎都與變量的值(比如上面這個例子裡的遞增操作或一個指派操作的計算結果)無法預料有關。