C hat keine eingebauten booleschen Typen. Was ist der beste Weg, um sie in C zu verwenden?
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
Wenn Sie unentschieden sind, fahren Sie mit # 1 fort!
Ein paar Gedanken zu Booleans in C:
Ich bin alt genug, dass ich einfach int
s 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.
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 .
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.
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;
}
typedef enum {
false = 0,
true
} t_bool;
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 false
iffa
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:
int
und Werte 0
und 1
wie besehen ein. und führen Sie Domänenkonvertierungen von anderen Werten mit doppelter Negation sorgfältig durch. !!
BOOL
, TRUE
und FALSE
!C hat einen booleschen Typ: bool (zumindest für die letzten 10 (!) Jahre)
Include stdbool.h und true/false funktionieren wie erwartet.
Alles, was nicht Null ist, wird in booleschen Operationen als wahr ausgewertet
#define TRUE 1
#define FALSE 0
und verwende die Konstanten.
@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.
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;
Es ist das:
#define TRUE 1
#define FALSE 0
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
.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.bool
true
und false
neu definieren, aber sicher ist dies keine gute Idee. Diese Fähigkeit gilt als veraltet und wird in Zukunft entfernt._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.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.