874 Stimmen

Verwendung boolescher Werte in C

C hat keine eingebauten booleschen Typen. Wie kann man sie am besten in C verwenden?

93 Stimmen

C hat einen booleschen Typ. Zumindest gibt es einen in den neuesten Standards.

12 Stimmen

1277voto

Thomas Bonini Punkte 42356

Vom Besten zum Schlechtesten:

Option 1 (C99 und neuere Versionen)

#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 (oder eine neuere Version) verwenden und dies die "Standardmethode" ist. Wählen Sie dies, wenn möglich.
  • Die Optionen 2, 3 und 4 haben in der Praxis das gleiche Verhalten. #2 und #3 verwenden jedoch keine #defines, was meiner Meinung nach besser ist.

Wenn Sie unentschlossen sind, wählen Sie die Nummer 1!

19 Stimmen

Können Sie das näher erläutern warum sind sie die beste bis schlechteste Wahl?

7 Stimmen

@endolith Die Ausrichtung, die Optimierungen und die Art und Weise der Speicherung eines <stdbool.h> bool der Compiler wählt, kann für den beabsichtigten Zweck eines booleschen Wertes besser geeignet sein als die Verwendung eines int (d.h. der Compiler kann sich für die Implementierung eines bool anders als ein int ). Wenn Sie Glück haben, kann dies auch zu einer strengeren Typüberprüfung bei der Kompilierung führen.

5 Stimmen

Warum verwenden int für bool ? Das ist Verschwendung. Verwenden Sie unsigned char . Oder verwenden Sie das in C eingebaute _Bool .

288voto

Dale Hagglund Punkte 15414

Ein paar Gedanken zu Booleschen Werten in C:

Ich bin alt genug, dass ich nur einfache int s als meinen booleschen Typ ohne Typendefinitionen oder spezielle Definitionen oder Enums für wahre/falsche Werte. Wenn Sie meinem Vorschlag folgen, niemals mit booleschen Konstanten zu vergleichen, müssen Sie ohnehin nur 0/1 verwenden, um die Flags zu initialisieren. Allerdings könnte ein solcher Ansatz in der heutigen Zeit als zu reaktionär angesehen werden. In diesem Fall sollte man auf jeden Fall <stdbool.h> da es zumindest den Vorteil hat, dass es standardisiert ist.

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

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

Diese können immer durch die klarere Variante ersetzt werden

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

Es ist zu beachten, dass diese Texte vernünftig und verständlich vorgelesen werden können.

Geben Sie Ihren booleschen Variablen positive Namen, d.h. full anstelle von notfull . Letzteres führt zu schwer lesbarem Code. Vergleiche

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

をもって

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

Die beiden erstgenannten Paare lesen sich natürlich, während !notfull ist schon in seiner jetzigen Form schwer zu lesen und wird bei komplexeren booleschen Ausdrücken noch viel schlimmer.

Boolesche Argumente sollten generell vermieden werden. Betrachten Sie eine Funktion, die wie folgt definiert ist

void foo(bool option) { ... }

Innerhalb des Funktionskörpers ist es sehr klar, was das Argument bedeutet, da es einen praktischen und hoffentlich sinnvollen Namen hat. Aber die Aufrufseiten sehen aus wie

foo(TRUE);
foo(FALSE):

Hier ist es im Grunde unmöglich, die Bedeutung des Parameters zu erkennen, ohne sich die Funktionsdefinition oder -deklaration anzusehen, und es wird noch viel schlimmer, wenn Sie noch mehr boolesche Parameter hinzufügen. Ich schlage vor, entweder

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

ou

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

In jedem Fall sieht die Aufrufsite jetzt wie folgt aus

foo(OPT_ON);
foo(OPT_OFF);

die der Leser zumindest einigermaßen verstehen kann, ohne die Definition des Begriffs foo .

1 Stimmen

Und wie kann man zwei Variablen auf Gleichheit vergleichen? Nie mit booleschen Konstanten funktioniert gut, aber es löst nicht das Problem, wenn der Vergleich gegen eine nicht-Konstante.

4 Stimmen

Verzeihen Sie mir, aber ich verstehe die Frage nicht. Fragen Sie, wie ich zwei boolesche Variablen auf Gleichheit vergleiche? Wenn ja, muss dann nicht a == b arbeiten?

0 Stimmen

Es funktioniert nicht, weil "a" den Wert 3 haben könnte, was wahr ist, und "b" den Wert 5 haben könnte, was wahr ist. Aber a == b sollte auch wahr sein, was nicht der Fall ist, wenn es sich um Ints handelt.

90voto

Fortega Punkte 19063

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

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

0 Stimmen

Es funktioniert auch gut mit logischen Operatoren (&& und ||).

85voto

Hier ist die Version, die ich verwendet habe:

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

Weil false nur einen Wert hat, ein logisches true aber viele Werte haben kann, setzt die Technik true als das, was der Compiler für das Gegenteil von false verwendet.

Damit ist das Problem gelöst, dass jemand etwas kodiert, das auf diese Weise zustande kommt:

if (true == !false)

Ich denke, wir sind uns alle einig, dass das 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 Systemen zu vermeiden, die true y false . Aber das Konzept bleibt das gleiche.

[EDIT] Um die Umwandlung von Integer in Boolean zu zeigen:

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

Die erste (rechte) ! konvertiert die Nicht-Null-Ganzzahl in eine 0, dann die zweite (linke) ! konvertiert die 0 in eine myfalse Wert. Ich überlasse es dem Leser als Übung, eine ganze Zahl von Null zu konvertieren.

[EDIT] Es ist mein Stil, die explizite Einstellung eines Wertes in einer Aufzählung zu verwenden, wenn der spezifische Wert erforderlich ist, auch wenn der Standardwert derselbe wäre. Beispiel: Weil false Null sein muss, verwende ich false = 0, statt false,

[EDIT] Zeigt, wie man die Größe von enum beim Kompilieren mit gcc begrenzt:

typedef __attribute__((__packed__)) enum { myfalse = 0, mytrue = !myfalse } mybool;

Das heißt, wenn es jemand tut:

struct mystruct {
    mybool somebool1;
    mybool somebool2;
    mybool somebool3;
    mybool somebool4;
}

beträgt die Größe der Struktur 4 Byte statt 16 Byte.

7 Stimmen

Ein weiterer Vorteil der Verwendung von Enums ist die IDE-Integration - true , false y bool werden in den meisten IDEs hervorgehoben, weil sie Enum-Werte und ein Typedef sind, im Gegensatz zu #defines die selten in der Syntax hervorgehoben werden.

1 Stimmen

Neugierig: Unabhängig davon, ob es tatsächlich funktioniert oder nicht, ist es gültig C(99+) zu erlauben, dass ein Enum einen früheren Wert in der gleiche Aufzählung ?

0 Stimmen

@tgm1024 gcc -ansi -pedantic -Wall gibt keine Warnungen, also vertraue ich gcc Wenn dies auch für c89 sollte es funktionieren für c99 ebenfalls.

53voto

Gary Willoughby Punkte 48229

Wenn Sie einen C99-Compiler verwenden, verfügt dieser über 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

0 Stimmen

Sie sind nicht als solche "eingebaut", sondern nur in der Include-Datei typisiert stdbool.h Sie enthalten also typedef enum {false, true} bool; in der Include-Datei

2 Stimmen

@JamesStevens Das ist nicht richtig. Es gibt einen eingebauten Typ namens _Bool . Es handelt sich nicht um eine Aufzählung. bool , true y false sind Makros, die in <stdbool.h> die sich auf _Bool , 1 y 0 beziehungsweise. Siehe de.cppreference.com/w/c/types/boolean

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X