Ich habe Definitionen in C gesehen
#define TRUE (1==1)
#define FALSE (!TRUE)
Ist das notwendig? Was ist der Vorteil gegenüber der einfachen Definition von TRUE als 1 und FALSE als 0?
c
precompiler
Robert Harvey
quelle
quelle
#define TRUE (’/’/’/’)
;#define FALSE (’-’-’-’)
(entnommen aus coding-guidelines.com/cbook/cbook1_1.pdf Seite 871)Antworten:
Bei diesem Ansatz wird der tatsächliche
boolean
Typ verwendet (und intrue
und aufgelöstfalse
), wenn der Compiler dies unterstützt. (speziell C ++)Es ist jedoch besser zu überprüfen, ob C ++ verwendet wird (über das
__cplusplus
Makro) und tatsächlichtrue
und zu verwendenfalse
.In einem C-Compiler entspricht dies
0
und1
.(Beachten Sie, dass das Entfernen der Klammern dies aufgrund der Reihenfolge der Operationen unterbricht.)
quelle
1==1
ist einint
. (Siehe stackoverflow.com/questions/7687403/… .)boolean
Typ?true
oder zurückfalse
.#define TRUE true
und#define FALSE false
wann immer__cplusplus
es definiert ist.Die Antwort ist Portabilität. Die numerischen Werte von
TRUE
undFALSE
sind nicht wichtig. Was ist wichtig, dass eine Aussage wieif (1 < 2)
auswertet zuif (TRUE)
und eine Erklärung wieif (1 > 2)
auswertet zuif (FALSE)
.Zugegeben, in C wird
(1 < 2)
ausgewertet1
und(1 > 2)
ausgewertet.0
Wie andere bereits gesagt haben, gibt es für den Compiler keinen praktischen Unterschied. Aber indem man die Compiler definierenTRUE
undFALSE
nach seinen eigenen Regeln, Sie machen ihre Bedeutung für Programmierer explizit, und Sie garantieren Konsistenz in Ihrem Programm und andere Bibliothek (die andere Bibliothek unter der Annahme folgt Standards C ... du würdest sei erstaunt).Einige Geschichte
Einige BASICs definiert
FALSE
als0
undTRUE
als-1
. Wie viele moderne Sprachen interpretierten sie jeden Wert ungleich Null alsTRUE
, aber sie bewerteten boolesche Ausdrücke, die wahr waren als-1
. IhreNOT
Operation wurde implementiert, indem 1 hinzugefügt und das Zeichen umgedreht wurde, da dies effizient war. So wurde 'NICHT x'-(x+1)
. Ein Nebeneffekt davon ist, dass ein Wert wie5
bewertetTRUE
, aberNOT 5
bewertet-6
, was auch istTRUE
! Es macht keinen Spaß, diese Art von Fehler zu finden.Best Practices
Angesichts der De-facto- Regeln, als die Null interpretiert wird
FALSE
und jeder Wert ungleich Null als interpretiert wirdTRUE
, sollten Sie niemals boolesch aussehende Ausdrücke mitTRUE
oder vergleichenFALSE
. Beispiele:Warum? Weil viele Programmierer die Abkürzung verwenden,
int
s alsbool
s zu behandeln. Sie sind nicht gleich, aber Compiler erlauben es im Allgemeinen. So ist es zum Beispiel völlig legal zu schreibenDas sieht legitim aus und der Compiler wird es gerne akzeptieren, aber es macht wahrscheinlich nicht das, was Sie wollen. Das liegt daran, dass der Rückgabewert von
strcmp()
ist0 if
yourString == myString
<0 if
yourString < myString
> 0 if
yourString > myString
Die obige Zeile kehrt also
TRUE
nur zurück, wennyourString > myString
.Der richtige Weg, dies zu tun, ist entweder
oder
Ähnlich:
Einige dieser "schlechten Beispiele" finden Sie häufig im Produktionscode, und viele erfahrene Programmierer schwören darauf: Sie funktionieren, einige sind kürzer als ihre (pedantisch?) Richtigen Alternativen, und die Redewendungen sind fast allgemein anerkannt. Aber bedenken Sie: Die "richtigen" Versionen sind nicht weniger effizient, sie sind garantiert portabel, sie bestehen selbst die strengsten Linters und selbst neue Programmierer werden sie verstehen.
Ist das das nicht wert?
quelle
(1==1)
ist nicht tragbarer als1
. Die eigenen Regeln des Compilers sind die der C-Sprache, die klar und eindeutig in Bezug auf die Semantik von Gleichheits- und Vergleichsoperatoren ist. Ich habe noch nie einen Compiler gesehen, der dieses Zeug falsch verstanden hat.strcmp
ist bekannt, dass der von zurückgegebene Wert kleiner als, gleich oder größer als 0 ist. Es ist nicht garantiert, dass er -1, 0 oder 1 ist, und es gibt Plattformen in freier Wildbahn, die diese Werte nicht zurückgeben, um die Implementierungsgeschwindigkeit zu erhöhen. Also wennstrcmp(a, b) == TRUE
danna > b
aber umgekehrte Implikation möglicherweise nicht gilt.(1==1)
und1
sind beide konstanten Ausdrücke des Typsint
mit dem Wert 1. Sie semantisch identisch sind. Ich nehme an, Sie können Code schreiben, der sich an Leser richtet, die das nicht wissen, aber wo endet er?Der
(1 == 1)
Trick ist nützlich zum DefinierenTRUE
auf eine Weise , die für C transparent ist und dennoch eine bessere Eingabe in C ++ ermöglicht. Der gleiche Code kann als C oder C ++ interpretiert werden, wenn Sie in einem Dialekt namens "Clean C" schreiben (der entweder als C oder C ++ kompiliert wird) oder wenn Sie API-Header-Dateien schreiben, die von C- oder C ++ - Programmierern verwendet werden können.Hat in C-Übersetzungseinheiten
1 == 1
genau die gleiche Bedeutung wie1
; und1 == 0
hat die gleiche Bedeutung wie0
. Hat jedoch in den C ++ - Übersetzungseinheiten den1 == 1
Typbool
. Das soTRUE
definierte Makro lässt sich also besser in C ++ integrieren.Ein Beispiel für eine bessere Integration ist beispielsweise, wenn die Funktion
foo
überlastet istint
und für hatbool
,foo(TRUE)
diebool
Überlastung ausgewählt wird. WennTRUE
es nur als definiert ist1
, funktioniert es in C ++ nicht gut.foo(TRUE)
will das wollenint
Überlastung.Natürlich eingeführt C99
bool
,true
undfalse
diese können in Header - Dateien verwendet werden , dass die Arbeit mit C99 und mit C.Jedoch:
TRUE
undFALSE
als(0==0)
und(1==0)
vor C99.Wenn Sie in einem gemischten C- und C ++ - Projekt arbeiten und C99 nicht möchten, definieren Sie die Kleinbuchstaben
true
.false
undbool
stattdessen.Davon abgesehen, die
0==0
abgesehen wurde (wird?) Trick von einigen Programmierern sogar in Code verwendet, der niemals dazu gedacht war, in irgendeiner Weise mit C ++ zusammenzuarbeiten. Das kauft nichts und deutet darauf hin, dass der Programmierer ein Missverständnis darüber hat, wie Boolesche Werte in C funktionieren.Falls die C ++ - Erklärung nicht klar war, finden Sie hier ein Testprogramm:
Die Ausgabe:
Zur Frage aus den Kommentaren, wie überladene C ++ - Funktionen für die gemischte C- und C ++ - Programmierung relevant sind. Diese veranschaulichen nur einen Typunterschied. Ein gültiger Grund dafür, dass eine
true
Konstantebool
beim Kompilieren als C ++ verwendet werden soll, ist die saubere Diagnose. Bei den höchsten Warnstufen warnt uns ein C ++ - Compiler möglicherweise vor einer Konvertierung, wenn wir eine Ganzzahl alsbool
Parameter übergeben. Ein Grund für das Schreiben in Clean C ist nicht nur, dass unser Code portabler ist (da er von C ++ - Compilern verstanden wird, nicht nur von C-Compilern), sondern wir können auch von den diagnostischen Meinungen von C ++ - Compilern profitieren.quelle
TRUE
unter C ++ unterscheiden.#ifdef __cplusplus
Ihre Absicht viel klarer ausdrücken.bool
undint
in der Praxis keine große Rolle spielen, da sie implizit ineinander konvertierbar sind (und in C tatsächlich "gleich" die Anführungszeichen beachten obwohl,) und es gibt nicht viele Situationen , in denen Sie wirklich brauchen disambuigate zwischen den beiden. "nicht viel" war wahrscheinlich zu schwer, "viel weniger im Vergleich zu Code mit Vorlagen und Überladung" wäre vielleicht besser gewesen.ist äquivalent zu
in C.
Das Ergebnis der Vergleichsoperatoren ist
0
oder1
.1==1
wird garantiert bewertet1
und!(1==1)
wird garantiert bewertet0
.Es gibt absolut keinen Grund, das erste Formular zu verwenden. Beachten Sie, dass das erste Formular jedoch nicht weniger effizient ist, da bei fast allen Compilern ein konstanter Ausdruck eher zur Kompilierungszeit als zur Laufzeit ausgewertet wird. Dies ist nach dieser Regel zulässig:
PC-Lint gibt sogar eine Nachricht aus (506, Boolescher Wert mit konstantem Wert), wenn Sie kein Literal für
TRUE
undFALSE
Makros verwenden:Auch in C99 verwenden die
stdbool.h
Definitionen für Boolesche Makrostrue
undfalse
direkt Literale:quelle
1==1
wird garantiert bis1
if(foo == true)
, der von einer schlechten Praxis zu einem fehlerhaften Buggy wird.(x == TRUE)
kann einen anderen Wahrheitswert haben alsx
.Neben C ++ (bereits erwähnt) sind statische Analysewerkzeuge ein weiterer Vorteil. Der Compiler beseitigt Ineffizienzen, aber ein statischer Analysator kann seine eigenen abstrakten Typen verwenden, um zwischen Vergleichsergebnissen und anderen ganzzahligen Typen zu unterscheiden. Daher weiß er implizit, dass TRUE das Ergebnis eines Vergleichs sein muss und nicht als kompatibel angenommen werden sollte mit einer ganzen Zahl.
Offensichtlich sagt C, dass sie kompatibel sind, aber Sie können sich dafür entscheiden, die absichtliche Verwendung dieser Funktion zu verbieten, um Fehler hervorzuheben - zum Beispiel, wenn jemand verwirrt hat
&
und&&
oder sie ihre Operator-Priorität verpfuscht haben.quelle
if (boolean_var == TRUE)
durch Erweiterung abfangen, aufif (boolean_var == (1 == 1))
den dank der erweiterten Typinformationen des(1 == 1)
Knotens in das Muster fälltif (<*> == <boolean_expr>)
.Der praktische Unterschied ist keiner.
0
wird ausgewertetfalse
und1
ausgewertettrue
. Die Tatsache, dass Sie einen booleschen Ausdruck (1 == 1
) oder1
zum Definieren verwendentrue
, macht keinen Unterschied. Sie werden beide ausgewertetint
.Beachten Sie, dass die C-Standardbibliothek einen bestimmten Header zum Definieren von Booleschen Werten enthält :
stdbool.h
.quelle
true
wird ausgewertet1
undfalse
ausgewertet0
. C weiß nichts über native boolesche Typen, sie sind nur Ints.int
mit dem Wert0
oder1
. C hat einen tatsächlichen booleschen Typ (_Bool
mit einem inbool
definierten Makro<stdbool.h>
, das jedoch nur in C99 hinzugefügt wurde, wodurch die Semantik der Operatoren für die Verwendung des neuen Typs nicht geändert wurde._Bool
und<stdbool.h>
hat#define bool _Bool
.1 == 1
Bewertung alsint
. Bearbeitet.Wir kennen den genauen Wert, dem TRUE entspricht, nicht und die Compiler können ihre eigenen Definitionen haben. Was Sie also privilegieren, ist die Verwendung des internen Compilers für die Definition. Dies ist nicht immer erforderlich, wenn Sie gute Programmiergewohnheiten haben, kann jedoch Probleme für einen schlechten Codierungsstil vermeiden, zum Beispiel:
if ((a> b) == TRUE)
Dies kann eine Katastrophe sein, wenn Sie TRUE manuell als 1 definieren, während der interne Wert von TRUE ein anderer ist.
quelle
>
liefert der Operator immer 1 für wahr, 0 für falsch. Es gibt keine Möglichkeit, dass ein C-Compiler dies falsch macht. GleichheitsvergleicheTRUE
undFALSE
schlechter Stil; das obige ist klarer geschrieben alsif (a > b)
. Aber die Idee, dass verschiedene C-Compiler Wahrheit und Falsch unterschiedlich behandeln können, ist einfach falsch.In der Programmiersprache C wird normalerweise 1 als wahr und 0 als falsch definiert. Deshalb sehen Sie ziemlich oft Folgendes:
Jede Zahl ungleich 0 würde jedoch auch in einer bedingten Anweisung als wahr bewertet. Verwenden Sie daher Folgendes:
Sie können nur explizit zeigen, dass Sie versuchen, auf Nummer sicher zu gehen, indem Sie false gleich dem machen, was nicht wahr ist.
quelle