A:
C言語は標準のブール型を用意していない。ブール型のデータ型を選
ぶことは空間と時間を天秤にかけることである。どちらを選択するか
はプログラマーにまかせるのが一番である(intをブール型に選べば速
いだろうし、charをブール型に選べばデータの保存領域の節約になる。
けれどintより小さいデータ型を使うと、intに変換したりintから変
換するのでコードが大きくなったり遅くなるかもしれない)。
#defineを使うか列挙型を使うかはどっちでもいいことで、とくに興 味を引くようなことはない(質問2.22と17.10を参照のこと)。プログ ラムやプロジェクトで首尾一貫している限り、以下のどれを使っても かまわない
あるいは生の1と0を使うのもいい(変数の値を調べるときに列挙型の 値を展開してくれるようなデバッガーを使っているのであれば、列挙 型のほうがいいかもしれない)。
#define TRUE 1 #define YES 1
#define FALSE 0 #define NO 0
enum bool {false, true}; enum bool {no, yes};
以下のようなちょっと違った形を好む人もいる。
#define TRUE (1==1)あるいは"補助の"マクロ、例えば
#define FALSE (!TRUE)
#define Istrue(e) ((e) != 0)を定義する人もいる。どちらにしても大した効果はない(以下の質問 9.2を参照。また質問5.12と10.2も参照のこと)。
A:
C言語では、どんな非0の値も真と考えられることは真実である。しか
しこのことは「入力においてのみ」、すなわちブール値がくることを
期待されているところでだけなりたつ。組み込みの演算子によってブー
ル値が産み出されるときは、1か0であることが保証されている。よっ
てテスト
if ((a == b) == TRUE)は(TRUEが1であるかぎり)期待したとおりの結果を返す。しかしバカ げたことである。一般にTRUEやFALSEを相手に明示的にテストするこ とは望ましくない。なぜならライブラリ関数の中には(有名なのは isupper()、isalpha()など)条件が成立したときに非0の値を返すが、 その値は必ずしも1ではないものがある(さらに、もし君が「if((a == b) == TRUE)」が「if(a == b)」の改良版であると信じるのなら、な ぜそこで止めるのか。なぜ「if (((a == b) == TRUE) == TRUE)」を 使わないのか)。おおまかな目安としては、TRUEとFALSEを(あるいは 似た物を)ブール値をあらわす変数に代入する際や、関数の引数、ブー ル値を返す関数の戻り値としてだけ使うこと。けっして比較に使って はいけない。
プリプロセッサーのマクロのうち、TRUEやFALSE(もちろんNULLも)は コードの可読性を上げるのに使うのであって、あらわす値が変わる可 能性があるから使うのではない(質問5.3と5.10も参照のこと)。
一方、ブール値の取る値や、定義の仕方はどう見ても混乱を招く可能 性がある。プログラマーの中にはTRUEとFALSEマクロは混乱の度合を 増すだけだと考えている人もいる。
References:
K&R1 Sec. 2.6 p. 39, Sec. 2.7 p. 41; K&R2 Sec. 2.6
p. 42, Sec. 2.7 p. 44, Sec. A7.4.7 p. 204, Sec. A7.9 p. 206;
ANSI Sec. 3.3.3.3, Sec. 3.3.8, Sec. 3.3.9, Sec. 3.3.13,
Sec. 3.3.14, Sec. 3.3.15, Sec. 3.6.4.1, Sec. 3.6.5; ISO
Sec. 6.3.3.3, Sec. 6.3.8, Sec. 6.3.9, Sec. 6.3.13, Sec. 6.3.14,
Sec. 6.3.15, Sec. 6.6.4.1, Sec. 6.6.5; H&S Sec. 7.5.4 pp. 196-7,
Sec. 7.6.4 pp. 207-8, Sec. 7.6.5 pp. 208-9, Sec. 7.7 pp. 217-8,
Sec. 7.8 pp. 218-9, Sec. 8.5 pp. 238-9, Sec. 8.6 pp. 241-4;
"亀がアキレスに言ったこと".
A:
正しい。質問5.3を参照のこと。