web-dev-qa-db-ja.com

Cでブール値を使用する

Cには組み込みのブール型はありません。 Cでそれらを使用するための最良の方法は何ですか?

584
neuromancer

良いものから悪いものへ:

オプション1(C99)

#include <stdbool.h>

オプション2

typedef enum { false, true } bool;

オプション3

typedef int bool;
enum { false, true };

オプション4

typedef int bool;
#define true 1
#define false 0

説明

  • オプション1は、C99を使用していてそれが「標準的な方法」である場合にのみ機能します。可能であればこれを選択してください。
  • オプション2、3、4では、実際には同じ動作になります。 #2と#3は#defineを使っていませんが、私の考えではそれが良いです。

あなたが未定の場合は、#1に行きます!

911
Andreas Bonini

Cのブール値についてのいくつかの考察:

私は十分に古く、typedefも特別な定義もtrue/false値の列挙もなしに、単純なintsを私のブール型として使用するだけです。あなたがブール定数に対して決して比較しないで以下の私の提案に従うなら、あなたはとにかくフラグを初期化するために0/1を使う必要があるだけです。しかしながら、そのようなアプローチは現代においてはあまりにも反動的であると考えられるかもしれません。その場合、少なくとも標準化されているという利点があるため、<stdbool.h>を確実に使用する必要があります。

どのようなブール定数が呼び出されても、初期化にのみ使用してください。こんなことを書いたことがない

if (ready == TRUE) ...
while (empty == FALSE) ...

これらは常に明確に置き換えることができます 

if (ready) ...
while (!empty) ...

これらは実際には合理的にそして当然のことながら大声で読むことができることに注意してください。

あなたのブール変数に正の名前、すなわちfullではなくnotfullを付けてください。後者は、読みにくいコードになります。比較する

if (full) ...
if (!full) ...

if (!notfull) ...
if (notfull) ...

!notfullはそのままでも読むのが面倒で、前者のペアは両方とも自然に読んでいますし、より複雑なブール式ではもっと悪くなります。

通常、ブール引数は避けてください。このように定義された関数を考えます

void foo(bool option) { ... }

関数の本体の中では、引数が便利で、そしてうまくいけば意味のある名前を持っているので、引数が何を意味するのかは非常に明確です。しかし、通話サイトは次のようになります。

foo(TRUE);
foo(FALSE):

ここでは、常に関数の定義や宣言を見ない限り、パラメータが何を意味するのかを知ることは本質的に不可能であり、さらにブールパラメータを追加するとすぐにさらに悪化します。どちらでもいい

typedef enum { OPT_ON, OPT_OFF } foo_option;
void foo(foo_option option);

または

#define OPT_ON true
#define OPT_OFF false
void foo(bool option) { ... }

どちらの場合も、通話サイトは次のようになります。

foo(OPT_ON);
foo(OPT_OFF);

読者は少なくともfooの定義を捨てずに理解できる可能性があります。

210
Dale Hagglund

Cのブール値は整数です。偽の場合はゼロ、真の場合はゼロ以外です。

ブールデータ型 、セクション C、C++、Objective-C、AWK も参照してください。

79
Fortega

これが私が使ったバージョンです:

typedef enum { false = 0, true = !false } bool;

Falseには1つの値しかありませんが、論理的なtrueには多数の値がある可能性がありますが、技法は、falseが反対の場合にコンパイラが使用するものになるようにtrueに設定されます。

これは誰かがこれに降りかかるであろう何かをコーディングする問題の世話をする:

if (true == !false)

これは良い習慣ではないということに私たち全員が同意すると思いますが、 "true =!false"を実行するための一時的な費用として、この問題を排除します。

[編集]最後に私が使用した:

typedef enum { myfalse = 0, mytrue = !myfalse } mybool;

truefalseを定義していた他のスキーマとの名前の衝突を避けるため。しかし、概念は変わりません。

[編集]整数から真偽値への変換を表示するには:

mybool somebool;
int someint = 5;
somebool = !!someint;

最初(一番右)!ゼロ以外の整数を0に変換し、次に2番目(最も左)に変換します。 0をmyfalse値に変換します。読者がゼロの整数を変換するための練習としてそれを残します。 

64
Michael Potter

C99コンパイラを使用している場合は、bool型をサポートしています。

#include <stdbool.h>
int main()
{
  bool b = false;
  b = true;
}

http://en.wikipedia.org/wiki/Boolean_data_type

41
Gary Willoughby

まず最初に。 C、つまり、ISO/IEC 9899は19年間ブール型でした。これは、訪問時にアマチュア/アカデミック/プロの部分を組み合わせたCプログラミングのキャリアの長さ expected よりも長い時間ですこの質問。私の場合は、おそらく1〜2年でそれを超えています。これは、平均的な読者がCについて何かを学んでいる間、実際にはCにはブールデータ型があったことを意味します。

データ型には#include <stdbool.h>を使用し、truefalseおよびboolを使用します。または、含めないで、代わりに_Bool1、および0を使用します。


この回答スレッドには、さまざまなdangerousアドバイスがあります。それらに対処します。

typedef int bool;
#define true 1
#define false 0

カジュアルな読者-19年以内にCを習得した読者-は、boolactualboolデータ型であり、同様に動作しますが、動作しません!例えば

double a = ...;
bool b = a;

C99 bool/_Boolの場合、bfalseに設定されますiffaはゼロで、それ以外の場合はtrueでした。 typedefを配置すると、doubleintに強制されます-doubleの値がintの範囲内にない場合、動作は未定義です

当然、truefalseenumで宣言された場合も同様です。

偶数より危険なものは宣言しています

typedef enum bool {
    false, true
} bool;

現在1と0以外のすべての値は無効であり、そのような値をそのタイプの変数に割り当てる必要があるため、動作は完全に未定義です

したがって、iff何らかの不可解な理由でC99を使用することはできません。ブール変数を使用する必要があります。

  • タイプintおよび値0および1as-is;二重否定!!を使用して、他の値からこれらへのドメイン変換を慎重に行います
  • または、insistの場合、0が偽でゼロでないことを覚えていない場合、少なくともupperを使用しますcase、C99の概念と混同しないように:BOOLTRUEおよびFALSE
19
Antti Haapala
typedef enum {
    false = 0,
    true
} t_bool;
17
mouviciel

Cのブール型は、 bool です(少なくとも過去10年間)。

Stdbool.hをインクルードすると、true/falseが正しく動作します。

11
dmeister

ブール演算でゼロ以外の値はtrueと評価される

#define TRUE 1
#define FALSE 0

定数を使用してください。

8
ggambett

@トーマスマシューズ:条件式はゼロでなければ真と見なされますが、C標準では論理演算子自体が0か1のどちらかを返すことを要求しています。

@トム:#define TRUE!FALSEは悪く、まったく意味がありません。ヘッダーファイルがコンパイルされたC++コードに変換されると、問題が発生する可能性があります。

void foo(bool flag);

...

int flag = TRUE;
foo(flag);

いくつかのコンパイラはint => bool変換についての警告を出すでしょう。時々人々はこれを避けることによってこれを避けます:

foo(flag == TRUE);

式を強制的にC++ブール値にします。しかし、もしあなたが#TRUEを定義するなら!FALSEなら、あなたは結局次のようになるでしょう:

foo(flag == !0);

とにかくint-to-boolの比較をすることになり、それが警告を引き起こします。

1
jamesdlin

C99の使用が許可されている場合は、他の回答と説明を補足するだけです。

+-------+----------------+-------------------------+--------------------+
|  Name | Characteristic | Dependence in stdbool.h |        Value       |
+-------+----------------+-------------------------+--------------------+
| _Bool |   Native type  |    Don't need header    |                    |
+-------+----------------+-------------------------+--------------------+
|  bool |      Macro     |           Yes           | Translate to _Bool |
+-------+----------------+-------------------------+--------------------+
|  true |      Macro     |           Yes           |   Translate to 1   |
+-------+----------------+-------------------------+--------------------+
| false |      Macro     |           Yes           |   Translate to 0   |
+-------+----------------+-------------------------+--------------------+

私の好みのいくつか:

  • _Boolまたはboolname__?両方とも問題ありませんが、boolname__はキーワード_Boolよりも見た目が良いです。
  • boolname__および_Boolに使用できる値は、falsename__またはtruename__です。 falsename__またはtruename__の代わりに0または1を割り当てることは有効ですが、ロジックフローを読んで理解することは困難です。

標準からのいくつかの情報:

  • _Boolunsigned intではありませんが、グループ符号なし整数型の一部です。 0または1の値を保持するのに十分な大きさです。
  • しないでください。ただし、はい、booltruename__とfalsename__を再定義することはできますが、確かに良い考えではありません。この機能は廃止されたと見なされており、今後削除されます。
  • スカラー型(算術型とポインター型)を_Boolまたはboolname__に割り当てると、スカラー値が0と等しいか、0と比較される場合、それは0になります。は1です:_Bool x = 9;9は、xname__に割り当てられたときに1に変換されます。
  • _Boolは1バイト(8ビット)です。通常、プログラマは他のビットを使用しようとしますが、推奨されるのは、タイプcharname__ではなく、データの格納に1ビットのみが使用されることだけです。 8ビットが利用可能です。
1

あなたはそれをchar、あるいは他の小さなコンテナを使うことができます。

疑似コード

#define TRUE  1
#define FALSE 0

char bValue = TRUE;
0
Filip Ekberg

これです:

#define TRUE 1
#define FALSE 0
0
RngTng

_Boolを使用することもできますが、戻り値は整数でなければなりません(trueの場合は1、falseの場合は0)。ただし、 この回答 from daniweb forum から、およびこの他のstackoverflowからの この回答 で説明されているように、C++の場合と同様にboolを含めて使用することをお勧めします。質問:

_Bool:C99のブール型。 _Boolを直接使用することが推奨されているのは、bool、true、またはfalseのマクロをすでに定義している従来のコードを保守している場合だけです。それ以外の場合、それらのマクロはヘッダーで標準化されています。そのヘッダを含めると、C++の場合と同じようにboolを使用できます。

0
Lokian