C++ &&、||、!邏輯運算子用法詳解

2020-07-16 10:04:39
邏輯運算子可以將兩個或多個關係表示式連線成一個或使表示式的邏輯反轉。本節將介紹如何使用邏輯運算子將兩個或多個關係表示式組合成一個。表 1 列出了 C++ 的邏輯運算子。

表 1 邏輯運算子
運算子 含義 效 果
&& 將兩個表示式連線成一個。兩個表示式必須都為 true,整個表示式才為 true
|| 將兩個表示式連線成一個。必須有一個或兩個表示式為 true,才能使整個表示式為 true。只要其中有一個為 true,那麼另外一個就變得無關緊要
反轉一個表示式的“真相”。它使一個表示式從 true 變成了 false,或者從 false 變成了 true

&& 運算子

&& 運算符被稱為邏輯與運算子。它需要兩個表示式作為運算元,並建立一個表示式,只有當兩個子表示式都為 true 時,該表示式才為 true。

以下是使用 && 運算子的 if 語句範例:

if ((temperature <20) && (minutes > 12))
    cout << "The temperature is in the danger zone.";

請注意,這兩個被邏輯與運算子連線在一起的表示式都是完整的表示式,它們的值可以被評估為 true 或 false。首先評估 temperature<20 以產生 true 或 false 的結果,然後評估 minutes>12 以產生 true 或 false 的結果,最後,這兩個結果被 AND 並列在一起,以得出整個表示式的最終結果。

僅當 temperature 小於 20 且 minutes 大於 12 時,cout 語句才會執行,其中只要有一個表示式的結果被評估為 false,則整個表示式為 false,不執行 cout 語句。

表 2 顯示了 && 運算子的真值表。該真值表列出了兩個表示式可能的值及其所有可能的組合,以及由連線兩個表示式的 && 操作返回的結果值。

表 2 邏輯與
子表示式值所有可能的組合 整體表示式的值
false && false false(0)
false && true false(0)
true && false false(0)
true && true true(1)

如該表所示,要使 && 運算子返回 true 值,則兩個子表示式都必須為 true。

注意,如果 && 運算子左側的子表示式為 false,則不會檢查右側的表示式。因為只要有一個子表示式為 false,則整個表示式都為 false,所以再檢查剩餘的表示式會浪費 CPU 時間。這被稱為短路評估

|| 運算子

|| 運算子被稱為邏輯或運算子。它需要兩個表示式作為運算元,並建立一個表示式,當任何一個子表示式為 true 時,該表示式為 true。

以下是一個使用 || 運算子的 if 語句範例:

if ((temperature < 20) || (temperature > 100))
    cout << "The temperature is in the danger zone.";

如果 temperature 小於 20 或者大於 100,那麼 cout 語句將被執行。這兩個子表示式只要其中一個為 true,則整個表示式為 true,執行 cout 語句。

注意,被邏輯或連線在一起的兩件事情應該都是邏輯表示式,它們的值為 true 或 false,按以下形式書寫的if條件是不正確的:

if (temperature <20 || >100)

表 3 顯示了或(||)運算子的真值表。

表 3 邏輯或運算子真值表
子表示式值所有可能的組合 整體表示式的值
false || false false(0)
false || true true(1)
true || false true(1)
true || true true(1)

只要其中一個子表示式為 true,則整體表示式為 true,此時另外一個子表示式無論是 false 還是 true 都無關緊要。

需要注意的是,|| 運算子也將進行短路評估。如果 || 運算子左側的子表示式為 true,則右側的子表示式將不被檢查,因為只要有一個子表示式為 true,那麼整體表示式就可以被評估為 true。

! 運算子

! 運算子被稱為邏輯非運算子,執行邏輯 NOT 操作。它可以反轉一個運算元的真值或假值。換句話說,如果表示式為 true,那麼 ! 運算子將返回 false,如果表示式為 false,則返回 true。

以下是一個使用 ! 運算子的 if 語句範例:

if (!(temperature > 100))
    cout << "You are below the maximum temperature. n";

首先,表示式 (temperature > 100) 將被測試為 true 或 false,然後!運算子被應用於該值。如果表示式 (temperature>100) 為 true,則!運算子返回 false。如果為 false,則!運算子返回 true。在該例子中,它相當於問“溫度是不是不大於 100?”或“溫度大於 100 是不是假的?”

表 4 顯示了非(!)運算子的真值表。

表 4 邏輯非運算子的真值表
表示式 表示式的值
! false true(1)
! true false(0)

布林變數和!運算子

布林變數的一個有趣特性是它的值可以簡單地通過命名來測試。假設 moreData 是一個布林變數,其測試語句如下:

if (moreData == true)

它可以簡寫為:

if (moreData)

再來看以下語句:

if (moreData == false)

它可以使用邏輯非運算子簡寫為:

if (! moreData)

&&、|| 和 ! 的優先順序

&&、|| 和 !的優先順序為:

! > && > ||

! 運算子比許多 C++ 運算子具有更高的優先順序。因此,為了避免錯誤,應始終將其運算元括在括號中,除非打算將其應用於沒有其他操作符的變數或簡單表示式。例如,來看以下表示式:

! (x > 2)
! x > 2

第一個表示式將 !運算子應用於表示式 x>2,它是在問“x 是否不大於 2”,然而,第二個表示式是將 !運算子應用於到 x。它是在問“x 的邏輯是否大於 2”。假設 x 被設定為 5,由於 5 是非零值,所以被認為是 true,而 !運算子會將其反轉為 false,即為 0,然後,> 運算子將確定 0 是否大於 2。為了避免這種錯誤,始終使用括號是明智的。

&& 和 || 運算子的優先順序低於關係運算子,這意味著關係表示式先進行計算,然後再通過 && 和 || 運算子進行評估,因此有:

a > b && x < y 等同於(a > b) && (x < y)
a > b || x < y 等同於(a > b) | | (x < y)

因此,在關係運算子與 && 和 || 混合時,通常不需要括號。當然,無論如何,使用括號都是一個好主意,因為它們可以讓程式更易讀。

在 && 和 || 同時使用的情況下,更是強烈地推薦使用括號,這是因為 && 的優先順序高於 ||。如果沒有括號表示執行順序,那麼 && 將永遠在 || 之前完成,這可能並不符合編寫者的初衷。

例如,假設有 3 個布林變數 recentGrad、employed 和 goodCredit,則以下表示式:

recentGrad || employed && goodCredit

等同於以下表示式:

recentGrad || (employ && goodCredit)

但是它並不等同於以下表示式:

(recentGrad || employed)&& goodCredit