C言語学習ポータル(無料版) 学習コンテンツ 制御構造 論理演算子と短絡評価

🔀 制御構造

論理演算子と短絡評価

無料公開版に収録・読む目安 12分

🎯 && || ! で複数の条件を組み立てられるようになり、短絡評価の性質を安全のために利用できる

遊園地の乗り物に、こんな看板があります。「身長120cm以上、かつ、大人の同伴がある方」。条件が2つ以上あるとき、日本語の「かつ」「または」「〜でない」をCに翻訳するのが論理演算子です。

&& は「かつ」。両方が真のときだけ真になります。

|| は「または」。どちらかが真なら真になります。

! は「〜でない」。真と偽をひっくり返します。

実際に使ってみましょう。

#include <stdio.h>

int main(void) {
    int height = 125;
    bool hasTicket = true;

    if (height >= 120 && hasTicket) {
        printf("ご乗車できます\n");
    } else {
        printf("ごめんなさい、条件を満たしていません\n");
    }
    return 0;
}

hasTicket を && hasTicket == true と書かなくてよいのは、前のトピックのとおりです。

さて、ここで数学の書き方をそのまま持ち込むと事故ります。「x が 0 以上 100 以下」を、こう書きたくなりませんか。

    if (0 <= x <= 100) {        // これは常に真!
        printf("範囲内です\n");
    }

コンパイルは通ります。警告すら出ないことがあります。しかしどんな x でも必ず真になります。Cは左から順に処理するので、まず 0 <= x を判定して true(1) か false(0) という値にします。次に残った式が 1 <= 100 か 0 <= 100 になり、どちらも成り立ってしまうのです。正しくはこう書きます。

#include <stdio.h>

int main(void) {
    int x = 250;

    if (0 <= x && x <= 100) {   // 比較はそれぞれ完全な形で
        printf("範囲内です\n");
    } else {
        printf("範囲外です\n");
    }
    return 0;
}
師範0 <= x <= 100 が通ってしまうのは、比較の結果がまた数値になるからじゃ。Cは律儀に、左から2回比べておる

もうひとつ知っておくべき性質が短絡評価です。A && B は、A が偽だと分かった時点で B を評価しません。結果はもう偽で確定しているからです。同じく A || B は A が真なら B を見ません。これは「たまたまそうなる」のではなく、C言語の仕様で保証された動きです。

この性質は、防波堤として使えます。

#include <stdio.h>

int main(void) {
    int total = 10;
    int count = 0;

    if (count != 0 && total / count > 3) {   // count が 0 なら右は評価されない
        printf("平均は3より大きい\n");
    } else {
        printf("平均は計算できません\n");
    }
    return 0;
}

count が 0 のとき、total / count は0除算でプログラムが異常終了します。しかし左の count != 0 が偽になった瞬間に判定は打ち切られ、割り算は実行されません。もし左右を入れ替えて total / count > 3 && count != 0 と書いたら、その場でクラッシュします。守りの条件を左に置く——これは後々ポインタを扱うときにも命綱になる書き方です。

最後に細かい注意を2つ。&& は || より先に結合するので、混ぜて使うときはかっこを付けて意図をはっきりさせてください。a || b && c は a || (b && c) です。そして ! は結合が強いので、!a == b は (!a) == b になります。迷ったらかっこ、で構いません。

まとめます。&& は「かつ」、|| は「または」、! は「でない」。範囲は 0 <= x && x <= 100。短絡評価のおかげで、左に守りの条件を置けば右は安全に書ける。

要点まとめ

アプリで演習問題まで解く(無料・登録不要)

この項目に出てくる用語

演算子えんざんし

+や-、==など、値どうしを計算したり比較したりするための記号のこと。演算子ごとに計算される優先順位があらかじめ決まっている。+ - * / のような算術演算子のほか、比較や論理の演算子も含まれる。

条件式じょうけんしき

真(true)か偽(false)のどちらかに評価される式のこと。if文やwhile文が「どちらへ進むか」を判断するための材料になる。true/falseで表される真偽値の型(bool)がこの評価結果にあたる。

短絡評価たんらくひょうか

&&や||で式を評価するとき、左側だけで結果が確定した時点で右側の評価を省略する仕組みのこと。ぬるぽ防止のガード条件などで活用される。if (p != NULL && *p == 1)のように、安全確認とセットで使われることが多い。

bool型ぶーるがた

true(真)かfalse(偽)のどちらかしか入らない型のこと。C23では標準の書き方としてbool・true・falseがそのまま使えるようになった。従来は0と1で真偽を表していたが、C23の書き方の方が意図が伝わりやすい。

同じトラックのほかの項目

流れを変える——制御構造の全体像プログラムの流れが「順次・分岐・繰り返し」の3つでできていることを理解し、場面に応じてどれを使うか見当をつけられ… if文——もしも、の分かれ道if文の書き方と条件式の考え方を理解し、条件によって処理を分けられるようになる else if / else の分かれ道設計else / else if で複数の分かれ道を作れるようになり、範囲判定の順序を正しく設計できる 条件式の罠——= と == の悲劇代入 = と比較 == の違いを説明でき、条件式で取り違えたときに何が起きるかを見抜ける switch文とfallthroughswitch文で値による多分岐を書けるようになり、break忘れによるフォールスルーを理解する for文——回数が決まった繰り返しfor文の3つの部品と実行順序を理解し、回数の決まった繰り返しを正しく書ける while文——条件が決める繰り返しwhile文で終わりの読めない繰り返しを書けるようになり、for との使い分けを判断できる do-while文と入力チェックdo-while の「まず1回は実行する」性質を理解し、入力のやり直しループを書ける breakとcontinueの使いどころbreak でループを打ち切り、continue で残りをスキップできるようになり、それぞれの副作用を避けられる ループのネストと九九表二重ループの動きを説明でき、九九表のような表形式の出力を自分で組み立てられる 無限ループとの付き合い方無限ループの原因を3つの型で診断でき、意図的な無限ループを出口つきで安全に書ける
‹ 条件式の罠——= と == の悲劇 switch文とfallthrough ›

もっと先へ:ポインタ・メモリ・ファイル入出力・セキュアコーディングを含む全26トラックと、段位検定・模試のフルセットは完全版に収録しています。

完全版(BOOTH)を見る

📚 姉妹教材:手を動かして覚える Linux 教材 — Linuxとインフラの仕組みを地図で学ぶ

Web版 / BOOTH