遊園地の乗り物に、こんな看板があります。「身長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。短絡評価のおかげで、左に守りの条件を置けば右は安全に書ける。