it-swarm.com.de

Boolesche Werte in C verwenden

C hat keine eingebauten booleschen Typen. Was ist der beste Weg, um sie in C zu verwenden?

584
neuromancer

Vom Besten zum Schlechten:

Option 1 (C99)

#include <stdbool.h>

Option 2

typedef enum { false, true } bool;

Option 3

typedef int bool;
enum { false, true };

Option 4

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

Erläuterung

  • Option 1 funktioniert nur, wenn Sie C99 verwenden. Dies ist die "Standardmethode". Wählen Sie dies wenn möglich.
  • Die Optionen 2, 3 und 4 haben in der Praxis dasselbe Verhalten. # 2 und # 3 verwenden nicht #defines, was meiner Meinung nach besser ist.

Wenn Sie unentschieden sind, fahren Sie mit # 1 fort!

911
Andreas Bonini

Ein paar Gedanken zu Booleans in C:

Ich bin alt genug, dass ich einfach ints als meinen booleschen Typ ohne Typedefs oder spezielle Definitionen oder Enums für True/False-Werte verwende. Wenn Sie meinem untenstehenden Vorschlag folgen und niemals mit booleschen Konstanten vergleichen, müssen Sie die Flags ohnehin nur mit 0/1 initialisieren. Ein solcher Ansatz kann jedoch in dieser modernen Zeit als zu reaktionär angesehen werden. In diesem Fall sollte definitiv <stdbool.h> verwendet werden, da es zumindest den Vorteil hat, standardisiert zu sein.

Wie auch immer die booleschen Konstanten aufgerufen werden, verwenden Sie sie nur zur Initialisierung. Schreiben Sie niemals so etwas

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

Diese können immer durch den Reiniger ersetzt werden 

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

Beachten Sie, dass diese tatsächlich vernünftig und verständlich laut vorgelesen werden können.

Geben Sie Ihren booleschen Variablen positive Namen, dh full statt notfull. Letzteres führt zu Code, der schwer lesbar ist. Vergleichen Sie

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

mit

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

Beide der vorherigen Paare lesen auf natürliche Weise, während !notfull noch unbequem zu lesen ist und in komplexeren booleschen Ausdrücken viel schlechter wird.

Boolesche Argumente sollten generell vermieden werden. Betrachten Sie eine so definierte Funktion

void foo(bool option) { ... }

Innerhalb des Körpers der Funktion ist es sehr klar, was das Argument bedeutet, da es einen bequemen und hoffentlich aussagekräftigen Namen hat. Aber die Anrufseiten sehen so aus

foo(TRUE);
foo(FALSE):

Es ist im Wesentlichen unmöglich zu sagen, was der Parameter bedeutete, ohne sich immer die Funktionsdefinition oder -deklaration anzusehen, und es wird viel schlimmer, wenn Sie noch mehr boolsche Parameter hinzufügen. Schlage ich vor

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

oder

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

In beiden Fällen sieht die Anrufseite jetzt so aus

foo(OPT_ON);
foo(OPT_OFF);

was der Leser zumindest eine Chance hat zu verstehen, ohne die Definition von foo zu verschleiern.

210
Dale Hagglund

Ein boolescher Wert in C ist eine ganze Zahl: Null für falsch und Nicht-Null für wahr.

Siehe auch Boolean-Datentyp, Abschnitt C, C++, Objective-C, AWK .

79
Fortega

Hier ist die Version, die ich verwendet habe:

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

Denn false hat nur einen Wert, aber ein logisches true kann viele Werte enthalten, aber als wahr gilt das, was der Compiler für das Gegenteil von false verwendet.

Dies kümmert sich um das Problem, dass jemand etwas codiert, das dazu führen würde:

if (true == !false)

Ich denke, wir sind uns alle einig, dass dies keine gute Praxis ist, aber für die einmaligen Kosten von "true =! False" beseitigen wir dieses Problem.

[EDIT] Am Ende habe ich verwendet:

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

um Namenskollisionen mit anderen Schemata zu vermeiden, die true und false definieren. Das Konzept bleibt jedoch gleich.

[EDIT] So zeigen Sie die Umwandlung von Ganzzahl in Boolean an:

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

Der erste (ganz rechts)! wandelt die Ganzzahl ungleich Null in eine 0 um, dann die zweite (ganz links)! wandelt die 0 in einen myfalse-Wert um. Ich werde es dem Leser als Übung überlassen, eine Nullzahl zu konvertieren. 

64
Michael Potter

Wenn Sie einen C99-Compiler verwenden, bietet er integrierte Unterstützung für Bool-Typen:

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

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

41
Gary Willoughby
typedef enum {
    false = 0,
    true
} t_bool;
17
mouviciel

Das wichtigste zuerst. C, d. H. ISO/IEC 9899 hat seit jetzt 19 Jahre einen booleschen Typ. Das ist viel länger als die erwartete - Länge der C-Programmierlaufbahn mit Amateur akademischen/professionellen Teilen, die zusammen mit diese Frage besucht werden. Meins übertrifft das vielleicht um 1-2 Jahre. Dies bedeutet, dass während der Zeit die ein durchschnittlicher Leser überhaupt etwas über C gelernt hat, C tatsächlich den booleschen Datentyp hatte.

Für den Datentyp #include <stdbool.h> verwenden Sie true, false und bool. Oder schließen Sie es nicht ein und verwenden Sie stattdessen _Bool, 1 und 0.


Es gibt verschiedene gefährliche Ratschläge in diesem Antwort-Thread. Ich werde sie ansprechen:

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

Dies ist kein Nein, da ein zufälliger Leser - der innerhalb dieser 19 Jahre C gelernt hat - erwarten würde, dass bool sich auf den Datentyp actualbool bezieht und sich ähnlich verhält, dies aber nicht! Zum Beispiel

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

Mit C99 bool/_Bool würde b auf falseiffa war Null gesetzt, andernfalls true. Wenn typedef vorhanden ist, wird double zu int gezwungen. Wenn der Wert des Doppels nicht im Bereich für int liegt, ist Verhalten ist undefiniert.

Gleiches gilt natürlich auch, wenn true und false in einem enum deklariert wurden.

Was ist sogar gefährlicher deklariert 

typedef enum bool {
    false, true
} bool;

da jetzt alle Werte außer 1 und 0 ungültig sind, und sollte ein solcher Wert einer Variablen dieses Typs zugewiesen werden, das Verhalten wäre völlig undefiniert.

Daher können Sie iff aus unerklärlichen Gründen nicht für C99 verwenden. Für boolesche Variablen sollten Sie Folgendes verwenden:

  • geben Sie int und Werte 0 und 1wie besehen ein. und führen Sie Domänenkonvertierungen von anderen Werten mit doppelter Negation sorgfältig durch. !!
  • oder wenn Sie beharren Sie sich nicht daran erinnern, dass 0 falsch und nicht null ist, verwenden Sie mindestens Großbuchstaben, damit sie nicht mit den C99-Konzepten verwechselt werden: BOOL , TRUE und FALSE!
16
Antti Haapala

C hat einen booleschen Typ: bool (zumindest für die letzten 10 (!) Jahre)

Include stdbool.h und true/false funktionieren wie erwartet.

11
dmeister

Alles, was nicht Null ist, wird in booleschen Operationen als wahr ausgewertet

#define TRUE 1
#define FALSE 0

und verwende die Konstanten.

8
ggambett

@Thomas Matthews: Bedingte Ausdrücke gelten als wahr, wenn sie nicht Null sind. Der C-Standard erfordert jedoch, dass die logischen Operatoren selbst entweder 0 oder 1 zurückgeben.

@Tom: #define TRUE! FALSE ist schlecht und völlig sinnlos. Wenn sich die Header-Datei in kompilierten C++ - Code einfügt, kann dies zu Problemen führen:

void foo(bool flag);

...

int flag = TRUE;
foo(flag);

Einige Compiler geben eine Warnung bezüglich der Konvertierung int => bool aus. Manchmal vermeiden die Leute dies, indem sie Folgendes tun:

foo(flag == TRUE);

um den Ausdruck zu zwingen, ein C++ - Bool zu sein. Wenn Sie jedoch TRUE! FALSE definieren, erhalten Sie am Ende Folgendes:

foo(flag == !0);

dies führt dazu, dass ein Int-to-Bool-Vergleich durchgeführt wird, der die Warnung trotzdem auslösen kann.

1
jamesdlin

Sie können dazu ein Zeichen oder einen anderen Container für kleine Zahlen verwenden.

Pseudo-Code

#define TRUE  1
#define FALSE 0

char bValue = TRUE;
0
Filip Ekberg

Es ist das:

#define TRUE 1
#define FALSE 0
0
RngTng

Nur eine Ergänzung zu anderen Antworten und ein paar Klarstellungen, wenn Sie C99 verwenden dürfen.

+-------+----------------+-------------------------+--------------------+
|  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   |
+-------+----------------+-------------------------+--------------------+

Einige meiner Vorlieben:

  • _Bool oder bool? Beide sind in Ordnung, aber bool sieht besser aus als das Schlüsselwort _Bool.
  • Zulässige Werte für bool und _Bool sind: false oder true. Die Zuweisung von 0 oder 1 anstelle von false oder true ist gültig, ist jedoch schwieriger zu lesen und den logischen Ablauf zu verstehen.

Einige Informationen vom Standard:

  • _Bool ist NICHT unsigned int, ist jedoch Teil der Gruppe vorzeichenlose Integer-Typen . Es ist groß genug, um die Werte 0 oder 1 aufzunehmen.
  • NICHT, aber ja, Sie können booltrue und false neu definieren, aber sicher ist dies keine gute Idee. Diese Fähigkeit gilt als veraltet und wird in Zukunft entfernt.
  • Zuweisung eines skalaren Typs (arithmetische Typen und Zeigertypen) zu _Bool oder bool, wenn der scalar - Wert gleich 0 ist oder mit 0 verglichen wird, ist dies 0, andernfalls lautet das Ergebnis 1: _Bool x = 9;9 Wird in 1 konvertiert, wenn x zugewiesen wird.
  • _Bool ist 1 Byte (8 Bit). Normalerweise versucht der Programmierer, die anderen Bits zu verwenden. Dies wird jedoch nicht empfohlen, da nur garantiert wird, dass nur ein Bit zum Speichern von Daten verwendet wird, nicht wie bei char 8 Bit zur Verfügung haben.
0

Sie könnten _Bool verwenden, aber der Rückgabewert muss eine Ganzzahl sein (1 für wahr, 0 für falsch). Es wird jedoch empfohlen, bool wie in C++ einzuschließen und zu verwenden, wie in dieser Antwort aus daniweb forum sowie dieser Antwort aus dieser anderen Stapelüberlauf-Frage angegeben:

_Bool: Boolescher Typ von C99. Die direkte Verwendung von _Bool wird nur empfohlen, wenn Sie älteren Code beibehalten, der bereits Makros für bool, true oder false definiert. Andernfalls werden diese Makros im Header standardisiert. Fügen Sie diesen Header ein, und Sie können bool wie in C++ verwenden.

0
Lokian