条件判定は演算子で行われますが、演算子の結果は全て真と偽という状態に変換されてから、最終的な分岐処理の実行に移ります。今回は C言語で重要な真 TRUE と偽 FALSE のお話です。
--いきなりここに飛んで来ちゃった人は、よろしければ下記からご覧ください。
C言語基礎講座インデックス
- そもそも真と偽の状態ってなに?
条件判定などの演算子の結果が成立すると真という状態になります。逆に条件が成立しなかったら偽となります。では、そもそも、この真偽ってどういう状態なのでしょうか。少し実験してみましょう。
int num; printf("適当な数値を入力してください。\n"); scanf_s("%d", &num); if (num) { printf("%dは真です。", num); } else { printf("%dは偽です。", num);
}
いきなり if の中に変数だけの状態です。これでエラーにならないのです。演算した結果が真と偽に変換されているので、このように結果だけを if に入れても動作します。では、どういう値を入れたら真と偽に分かれるのでしょうか。
数字の範囲が大きすぎて大変だと思いますので答えを言ってしまいますが、0 の時だけ偽と表示されます。それ以外は全て真です。これで分かるとおり、0 が偽で 0 以外が真なのです。これがまず C言語における条件判定の前提となります。
- TRUE と FALSE の定義
真と偽の状態を表現するための定数名である、真 = TRUE と偽 = FALSE は、元々 C言語では未定義なので、自分で定義をする必要があります。このとき、FALSE は 0 で良いのですが、TRUE をどうしようかと悩みかもしれません。通常は、以下のような定義とします。
#define FALSE 0 #define TRUE !FALSE
ついに使いました。! 否定演算子です。FALSE の反対が TRUE です。否定演算子とは、この TRUE と FALSE を入れ替える動作をしていたのです。!FALSE と書く事で、FALSE が否定された TRUE の値が格納されます。具体的にどういう値が入っているか?それは以下のプログラムを実行すると分かります。
#define FALSE 0 #define TRUE !FALSE void main() { printf("%dが真です。\n", TRUE); printf("%dが偽です。\n", FALSE);
}
VS2022 環境では、1 が真と表示されます。先にも説明したとおり、0 以外が TRUE なので実は 0 以外なら何でも良いのです。私が遙か昔に使っていた太古の C言語では、TRUE は -1 でした。-1 は 2進数で表すと 0b11111111 なので、0b00000000 のビット反転という意味では正しかったのだと思います。これを知ってる人は昭和の時代からのプログラマかも。※ 或いは C言語の歴史に詳しい人とか
※ 原木切り落としのハムを食べた事がありますが、本当に美味しくてビックリします。人数が集まるパーティとかでもてなすと最高です。- 判定の仕方と否定演算子
※ 大文字の TRUE / FALSE はユーザー定義定数、小文字の true / false はC言語組み込みの bool 型定数です。
※ 説明が少し遅れましたが真偽はそのときの状態を示しています。
if (Result == TRUE) { printf("正常です。\n"); }
こんな書き方をするとだいたいダメ出しされます。そもそも、最終的に真と偽という状態に変換されてから分岐しているのですから、こういう時は
if (Result) { printf("正常です。\n"); }
と記述するのが C言語的な記述です。どうしても条件判定に演算子を記述したいのであれば、
if (Result != FALSE) { printf("正常です。\n"); }
このように、FALSE と比較するのであればまだ許してもらえるかと思います。ちなみに昔は条件判定式の中で代入しても、何の警告もなかったため、判定しているつもりでうっかり…
if (Result = 1) { printf("正常です。\n"); }
とすると、Result に 1 が代入されて、結果、常に条件判定が 1 = 真となって、正常としか表示されなくなるバグが多発しました。このバグ、作ってしまうと本当に分かりにくくて、思い込みも重なってかなり難儀します。が、今のインテリセンスは、こういう時にバグじゃねぇの?って指摘するという素敵なおじさまになっちゃってます。

半分余分になりますが、こういうバグを防ぐために古き良きプログラマは書き方として…

半分余分になりますが、こういうバグを防ぐために古き良きプログラマは書き方として…
if (1 == Result) { printf("正常です。\n"); }
このように、判定する定数を左辺に記述するという手法を採用しました。これだとうっかり == を = と書いてしまっても、

このようにエラーとして確実に指摘されるようになります。なお、真は成立という意味の他に、正常という意味も持ちます。偽は非成立ですが、他には異常という意味も持ちます。現在の状態を表すような変数を保ちたい場合は、このような意味合いがありますので、なるべくそれに沿って値を使うようにしてください。成立・正常・成功の結果は 真 = TRUE、不成立・異常・失敗の結果は偽 = FALSE ですね。
- C言語に組み込まれた bool 型
現在のC言語講座では拡張子が cpp になっているので、実際には C++ 相当で動かしています。それもあって、最初から bool 型は int や float 等と同じく、普通に型として使う事が出来ます。bool 変数に格納可能な値は true と false です。自分で定数定義したモノは TRUE / FALSE と大文字で記述していますが、最初から組み込まれた数値としての true / false は小文字で表現されます。そして、true は 1 で、false は 0 と固定となっています。ちょっと試してみます。
void main() { bool result; result = 100; printf("値は%dです。\n", result); }
100 を代入していますが、値の表示結果は 1 となりました。この bool 型には 0 以外を入れると全て true、すなわち 1 に変えてしまうのです。なので、== true と判定しても間違いではなくなりましたが、すいません、私のようなロートルプログラマには大変気持ち悪く感じるので、今後とも出来れば != false と常に false と比較して頂けますと幸いです(汗
なお、bool 型の result に NULL を入れると false になります。以前、NULL は 0 と定義していますが、このように C言語においては 0 は特別な意味を持つ数値なのです。
※ 今回のご紹介は本気でオススメです!生ハムは美味い!!
※ 家庭で食べるのならこちらをオススメ。味は変わらず手軽な量です。ビールやワインが進む進む!ちょっぴり塩っぱくて香りが豊潤。一言でサイコーです!
- まとめ
- そもそも真と偽の状態ってなに?
- TRUE と FALSE の定義
- 判定の仕方と否定演算子
- C言語に組み込まれた bool 型
>> C言語基礎講座インデックスに戻る
※ 今回のご紹介は本気でオススメです!生ハムは美味い!!
※ 家庭で食べるのならこちらをオススメ。味は変わらず手軽な量です。ビールやワインが進む進む!ちょっぴり塩っぱくて香りが豊潤。一言でサイコーです!


コメント
コメント一覧 (6)
Bashは数字の0が真でそれ以外が偽だったので、UNIXは違うものだと疑問にも思わなかった。
AWKは数字の0と文字の”0”が偽になっていて、数字も全部文字扱いだから変なことになっていると思った。
Javascriptは数字の0は偽だが文字の”0”は真になっていて、素直に”0”のコードポイントで見ていると思った。
Rubyはブール型のfalseとnil以外、数字の0も文字の”0”も真だったので割り切りに驚いた。
空や0が一つだけ入った配列やリストの真偽も、言語によっていろいろありそうです。
内藤時浩
が
しました
昔のCPUでも0判別は大事な機能でしたので、これを真偽判定に利用したのは自然なことだったと言うことでしょうね。
話がそれますが、UNIX/POSIXはコマンドの返り値として正常終了:0、異常終了:その他となっています。返り値がエラーコードで、0ならエラーなし、それ以外ならエラーありということです。プログラムの真偽とは逆になっているのがもったいなかったと感じました。
内藤時浩
が
しました
冒頭で「TRUE と FALSE という状態に変換される」と書いていながら、すぐ後に「TRUE と FALSE は元々 C言語では未定義」となっています。
C言語は、変換する内容を未定義にしておくような曖昧な言語なのでしょうか?
もちろん「僕は」そんなことは無いと知っていますが、講座としては、初心者にわかりにくいように思います。
前者は「状態(概念)として」の話、後者は「定義(実際)として」の話で違うのですが、同じ単語を使ってしまっているのが問題です。
概念を「真・偽」、定義を「TRUE・FALSE」のようにすればよいのではないでしょうか?
(最後の部分、C++ の予約語が true・false と小文字になることもちゃんと説明しないと、ここでも混乱しそうです)
内藤時浩
が
しました