表達式是單個或多個相聯的計算單個值語句,當用於比較時表達式,會返回bool布爾數據類型true(真)或false(假)。假設編寫了如下函數:
bool isEven(int value);
// 前置條件:若且唯若value為偶數時,函數返回真
對於編譯器來說,表達式返回任何非0的整數為true,返回0為false。比如:
能執行if語句函數體中的所有代碼,而語句:
便會不執行函數體中的所有代碼。於是就可以在代碼中使用isEven()函數,以顯示數字奇偶的信息。比如:
if(isEven(j))
// j是even
else
// j是odd
簡單地說,代碼中的表達式越長,越難以理解。而條件邏輯是最容易出錯的地方,下面將介紹幾種可以用於簡化的重構技術。其核心是分解條件語句,將一個條件語句拆分為多個部分。這種能力是非常重要的,因為它能夠將跳轉邏輯和具體發生的細節區分開來。
邏輯非!只有一個輸入,如果輸入為true,那麼返回false;如果輸入為false,則返回true。比如,非true結果為false,非false結果為true,零之外的任何數字的非值都為false。
如果兩個輸入值都為true,那麼邏輯與&&返回true(即第一個值與第二個值都為true),任何非零數字與false進行邏輯與返回false。因此不要認為&&用於判斷兩個數是否相等,而是用於判斷兩個參數是否為true。
如果第一個表達式是布爾型且返回false,那麼第二個表達式將不會計算,這就是短路求值。短路運算很有用,你可以寫出若且唯若第一個條件為true時,才判斷第二個條件的表達式。比如:
當運行到if語句時,程序首先會判斷x是不是0,如果是0,便直接跳過,不會判斷第二個條件。如果沒有短路,則不得不這樣寫:
if(x !=0)
if(10 /x < 2)
使用短路運算,可以寫出清晰的代碼。
如果兩個值都為true或其中一個為true,邏輯或(||)返回true。和邏輯與一樣,邏輯或也可以進行短路計算,如果第一個條件為true,便不會檢查第二個。
實際上,日常用語和數學邏輯表達有時相悖的,當「!、!=、&&和||」一起出現時,很容易引起混淆。當說起某某情況不為真時,則要用到!或!=。比如,value不等於2或3:
if( value != 2 || value !=3 )
如果從數學觀點考察這個條件測試,則會發現只要value不等於2或value不等於3,if測試中的表達式均為true,而實際上卻是錯誤的。正確的理解是,只要不滿足value為2或3,if語句的條件測試就通過:
if( !(value == 2 || value == 3) )
但這條語句還不夠直觀,因為真正想測試的是value不等於2「與」value不等於3,則這個測試可以修改為:
if( value != 2 && value != 3 )
因為對於任何邏輯表達式p和q,按照摩根定律,以下關係恆成立:
!(a || b || c) == (!a)&& (!b) && (!c)
!(a && b && c) ==(!a) || (!b) || (!c)
一般來說,熟練的程式設計師會忽略括號,因為關係運算符(、>=)的優先級比邏輯運算符(&&和||)更高,但加了括號會將意圖描述得更清楚。在混合使用互相無關的運算符時,多寫幾個括號是個很好的習慣,畢竟代碼是寫給別人看的。因為C語言存在優先級的陷阱,導致程式設計師很容易犯錯誤。由於邏輯運算符的約束力比賦值運算符強,因此在大部分混合使用的表達式中,括號是必須的。比如:
while((c = getchar()) != EOF)
如果混合使用了字位運算和關係運算符,由於字位運算符(&和|)的優先級低於關係運算符(比如,==),因此不管出現在哪裡,都必須在表達式裡加上括號。即: