6.

C++のif文の論理演算子|&&・||・!と短絡評価の使い方

編集

C++のif文で使う論理演算子とは、複数の条件を組み合わせて1つの真偽値(truefalse)にまとめるための演算子で、論理AND &&・論理OR ||・論理NOT ! の3つがあります。たとえば「年齢が18以上 かつ 会員である」のように、複数の判定を1つのif条件にまとめたいときに使います。本記事では、3つの論理演算子の意味とコード例、短絡評価(short-circuit evaluation)の正確な挙動、優先順位とビット演算子との違い、よくある落とし穴までを解説します。

この記事の要点
  • C++のif文の論理演算子は &&(論理AND)||(論理OR)!(論理NOT)の3つ。
  • && は両方が真のとき真、|| はどちらかが真なら真、! は真偽を反転する。
  • 短絡評価により、&& は左辺が偽なら右辺を評価せず、|| は左辺が真なら右辺を評価しない。Nullチェックの安全な書き分けに使える。
  • 優先順位は ! > && > ||。意図を明確にするには括弧を付ける。
  • ビット演算子 &| とは別物。混同すると短絡評価が効かず、結果も変わる。
  • 代表的な落とし穴は === の取り違えと、短絡評価による副作用の未実行

 

論理演算子の一覧

C++のif文で条件を組み合わせる論理演算子は次の3つです。いずれも結果は bool 型(true または false)になります。

演算子 名称 意味 真になる条件
&& 論理AND(かつ) 左右の両方が真のときだけ真 true かつ 右 true
|| 論理OR(または) 左右のどちらかが真なら真 左か右の少なくとも一方が true
! 論理NOT(否定) 真偽を反転する(単項演算子) 対象が false のとき

※ C++では andornot という代替表記(演算子の別名キーワード)も使えますが、実務では記号 &&||! が一般的です。

 

論理AND(&&)のコード例

&& は「両方の条件が成り立つとき」に処理を実行します。次の例は、点数が0以上100以下のときだけ「有効」と判定します。

#include <iostream>

int main() {
    int score = 80;

    if (score >= 0 && score <= 100) { // 両方が真
        std::cout << "有効な点数" << std::endl;
    }
    return 0;
}

 

論理OR(||)のコード例

|| は「どちらか一方でも成り立てば」処理を実行します。次の例は、入力が 'y' または 'Y' のときに「はい」と判定します。

char c = 'Y';

if (c == 'y' || c == 'Y') { // どちらかが真
    std::cout << "はい" << std::endl;
}

 

論理NOT(!)のコード例

! は1つの値の真偽を反転する単項演算子です。!found は「found が偽のとき真」になります。

bool found = false;

if (!found) { // found が false なら真
    std::cout << "見つかりませんでした" << std::endl;
}

 

短絡評価(short-circuit evaluation)

C++の &&||短絡評価を行います。これは、左辺だけで結果が確定する場合、右辺を評価しない(実行しない)という仕様です。

演算子 右辺を評価しない条件 理由
&& 左辺が false のとき 左が偽なら、右が何であれ全体は偽で確定するため
|| 左辺が true のとき 左が真なら、右が何であれ全体は真で確定するため

この性質は、Nullチェックのように「先に安全性を確かめてから中身にアクセスする」場面で役立ちます。次の例では、左辺 p != nullptr が偽(=ポインタがNull)のとき、右辺 *p > 0 は評価されないため、Nullポインタの参照外しを防げます。

int* p = nullptr;

// 左辺が false なら、右辺 *p は評価されない(安全)
if (p != nullptr && *p > 0) {
    std::cout << "正の値" << std::endl;
}

もし順序を逆にして *p > 0 && p != nullptr と書くと、先に *p が評価されてNullポインタを参照してしまい、未定義動作(クラッシュなど)になります。安全チェックは必ず左側に置くのが定石です。

 

優先順位と括弧

論理演算子の優先順位は高い順に ! > && > || です。また、&&|| よりも比較演算子(==<> など)のほうが優先順位は高いため、a < b && c > d(a < b) && (c > d) と解釈されます。

ただし &&|| を混在させると意図が読み取りにくくなります。たとえば a || b && ca || (b && c) と解釈されます(&& が先)。誤読を防ぐため、意図を括弧で明示しましょう。

// 括弧なし:&& が || より優先 → a || (b && c)
if (a || b && c) { /* ... */ }

// 括弧で意図を明示(推奨)
if ((a || b) && c) { /* ... */ }

 

ビット演算子 & / | との違い(混同注意)

記号が似ているため 論理演算子 &&|| と、ビット演算子 &| を混同しがちですが、別物です。

項目 論理演算子 && / || ビット演算子 & / |
処理単位 条件全体の真偽(bool 整数の各ビットごと
短絡評価 あり(右辺を省略しうる) なし(両辺を必ず評価)
主な用途 if文などの条件判定 フラグ操作・ビット計算

if文の条件で誤って & を使うと、短絡評価が効かないうえ、ビット単位で計算されるため結果が変わることがあります。たとえば 2 && 1true(1)ですが、ビット演算 2 & 10(=偽扱い)になります。条件判定には必ず &&|| を使いましょう

 

落とし穴

注意したいポイント
  • === の取り違え: if (x = 5) は「比較」ではなく「代入」で、x に5を代入したうえで条件が常に真になります。等しいか調べるときは == を使います。
  • 短絡評価による副作用の未実行: if (ok && update())ok が偽だと、関数 update()呼ばれません。副作用(カウンタ更新・ログ出力など)を条件式の右側に書くと、実行されないことがあります。
  • ビット演算子との取り違え: 条件に &| を書くと短絡評価が効かず、結果も意図とずれることがあります。

 

よくある質問(FAQ)

Q. &&& はどちらを使えばいいですか?
A. if文などで条件の真偽を判定する目的なら &&(論理AND)を使います。& はビット演算用で、短絡評価がなく結果も異なるため、条件判定では使いません。

Q. 短絡評価は無効にできますか?
A. &&|| の短絡評価はC++の言語仕様であり、無効化はできません。両辺を必ず評価したい場合は、条件式の中で副作用を起こさず、先に各値を変数へ求めてから論理演算する設計にします。

Q. 3つ以上の条件はどう書きますか?
A. if (a && b && c) のように演算子をつなげられます。&&|| を混ぜるときは、優先順位の誤読を避けるため括弧で意図を明示してください。

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. コメントアウト
  2. 文字列の結合/連結
  3. 変数の宣言
  4. 定数の宣言
  5. if文
  6. if文の論理演算子
  7. for文
  8. データ型(文字列以外)
  9. データ型(文字列)
  10. 配列とfor文
  11. 配列の要素数
  12. 多次元配列とfor文
  13. 多次元配列の要素数
  14. 関数の定義と呼び出し

最近更新/作成されたページ