Diese Frage mag dumm klingen, aber warum werden die meisten Programmiersprachen mit einem Wert von 0 (null) und einem anderen Wert (ganzzahlig) 0
bewertet ?false
true
String-Vergleich
Da die Frage ein bisschen zu einfach erscheint, möchte ich mich ein bisschen näher erläutern: Zunächst mag es jedem Programmierer klar erscheinen, aber warum sollte es keine Programmiersprache geben - es mag tatsächlich eine geben, aber keine Ich habe verwendet - wo wird 0
ausgewertet true
und alle anderen [Ganzzahl] -Werte auf false
? Diese eine Bemerkung mag zufällig erscheinen, aber ich habe ein paar Beispiele, bei denen es eine gute Idee gewesen sein könnte. Nehmen wir zunächst das Beispiel eines Strings-Drei-Wege-Vergleichs. Ich nehme C strcmp
als Beispiel: Jeder Programmierer, der C als Muttersprache verwendet, könnte versucht sein, den folgenden Code zu schreiben:
if (strcmp(str1, str2)) { // Do something... }
Da strcmp
gibt, 0
was auswertet, false
wenn die Zeichenfolgen gleich sind, schlägt das, was der anfängliche Programmierer versucht hat, kläglich fehl und er versteht im Allgemeinen zunächst nicht, warum. Hätte stattdessen 0
ausgewertet, true
hätte diese Funktion in ihrem einfachsten Ausdruck verwendet werden können - dem obigen -, wenn sie auf Gleichheit verglichen worden wäre, und die richtigen Überprüfungen für -1
und 1
wären nur bei Bedarf durchgeführt worden. Wir hätten den Rückgabetyp die bool
meiste Zeit als (meiner Meinung nach) betrachtet.
Außerdem wollen wir einen neuen Typ einführen sign
, der nur Werte annimmt -1
, 0
und 1
. Das kann ziemlich praktisch sein. Stellen Sie sich vor, es gibt einen Raumschiff-Operator in C ++ und wir wollen ihn für std::string
(nun, es gibt bereits die compare
Funktion, aber der Raumschiff-Operator macht mehr Spaß). Die Erklärung wäre derzeit die folgende:
sign operator<=>(const std::string& lhs, const std::string& rhs);
Wäre 0
bewertet worden true
, dass es den Raumschiff-Operator nicht einmal geben würde, und wir hätten das so erklären operator==
können:
sign operator==(const std::string& lhs, const std::string& rhs);
Dies operator==
hätte den Drei-Wege-Vergleich sofort erledigt und könnte weiterhin verwendet werden, um die folgende Prüfung durchzuführen, während weiterhin geprüft werden kann, welche Zeichenfolge der anderen bei Bedarf lexikografisch überlegen ist:
if (str1 == str2) { // Do something... }
Alte Fehlerbehandlung
Wir haben jetzt Ausnahmen, so dass dieser Teil nur für die alten Sprachen gilt, in denen so etwas nicht existiert (zum Beispiel C). Wenn wir uns die Standardbibliothek von C (und auch die von POSIX) ansehen, können wir mit Sicherheit feststellen, dass maaaaany-Funktionen 0
bei Erfolg und jede andere Ganzzahl zurückkehren. Ich habe leider einige Leute gesehen, die solche Dinge getan haben:
#define TRUE 0
// ...
if (some_function() == TRUE)
{
// Here, TRUE would mean success...
// Do something
}
Wenn wir darüber nachdenken, wie wir in der Programmierung denken, haben wir oft das folgende Argumentationsmuster:
Do something
Did it work?
Yes ->
That's ok, one case to handle
No ->
Why? Many cases to handle
Wenn wir noch einmal darüber nachdenken, hätte es Sinn gemacht, den einzigen neutralen Wert, 0
to yes
(und so funktionieren die Funktionen von C) zu setzen, während alle anderen Werte vorhanden sein können, um die vielen Fälle von zu lösen no
. Ich weiß jedoch, in allen Programmiersprachen (außer vielleicht einige experimentelle esotherische Sprachen), die yes
ausgewertet false
in einem if
Zustand, während alle no
Fälle auswerten zu true
. Es gibt viele Situationen, in denen "es funktioniert" einen Fall darstellt, während "es funktioniert nicht" viele wahrscheinliche Ursachen darstellt. Wenn wir so darüber nachdenken , wäre es viel sinnvoller gewesen, den Rest zu 0
bewerten .true
false
Fazit
Mein Fazit ist im Wesentlichen meine ursprüngliche Frage: Warum haben wir Sprachen entworfen, wo 0
ist false
und die anderen Werte sind true
, unter Berücksichtigung meiner wenigen obigen Beispiele und vielleicht einiger weiterer, an die ich nicht gedacht habe?
Follow-up: Es ist schön zu sehen, dass es viele Antworten mit vielen Ideen und möglichst vielen Gründen dafür gibt. Ich finde es toll, wie leidenschaftlich du darüber zu sein scheinst. Ich habe diese Frage ursprünglich aus Langeweile gestellt, aber da Sie so leidenschaftlich zu sein scheinen, habe ich beschlossen, ein wenig weiter zu gehen und nach den Gründen für die boolesche Wahl für 0 und 1 in Math.SE zu fragen :)
quelle
strcmp()
ist kein gutes Beispiel für wahr oder falsch, da es 3 verschiedene Werte zurückgibt. Und Sie werden überrascht sein, wenn Sie eine Shell verwenden, bei der 0 für wahr und alles andere für falsch steht.if true ; then ... ; fi
, bei dertrue
es sich um einen Befehl handelt, der Null zurückgibt und derif
zur Ausführung auffordert...
.bool
Typ , aber Vergleiche / if Bedingungen usw. können einen beliebigen Rückgabewert haben.Antworten:
0
ist,false
weil sie beide Null-Elemente in gemeinsamen semirings sind . Obwohl es sich um unterschiedliche Datentypen handelt, ist die Konvertierung zwischen ihnen intuitiv sinnvoll, da sie zu isomorphen algebraischen Strukturen gehören.0
ist die Identität für die Addition und Null für die Multiplikation. Dies gilt für ganze und rationale Zahlen, jedoch nicht für IEEE-754-Gleitkommazahlen:0.0 * NaN = NaN
und0.0 * Infinity = NaN
.false
ist die Identität für Boolean xor (() und Null für Boolean und (∧). Wenn Boolesche Werte als {0, 1} dargestellt werden - die Menge der Ganzzahlen modulo 2 -, können Sie sich ⊻ als Addition ohne Übertrag und ∧ als Multiplikation vorstellen.""
und[]
sind Identität für die Verkettung, aber es gibt mehrere Operationen, für die sie als Null sinnvoll sind. Wiederholung ist eine, aber Wiederholung und Verkettung verteilen sich nicht, sodass diese Operationen kein Semiring bilden.Solche impliziten Konvertierungen sind in kleinen Programmen hilfreich, aber in großen Programmen kann es schwieriger sein, darüber nachzudenken. Nur einer der vielen Kompromisse beim Sprachdesign.
quelle
nil
ist sowohl die leere Liste[]
als auch derfalse
Wert in Common Lisp; besteht die Tendenz, Identitäten aus verschiedenen Datentypen zusammenzuführen?) Sie müssen noch erklären, warum es selbstverständlich ist, Falsch als additive Identität und Wahr als multiplikative Identität zu betrachten und nicht umgekehrt. Ist es nicht möglich,true
als das Identifizieren fürAND
und Null für zu betrachtenOR
?true
ist auch die Identität und die Null der Semirings (Boolean und / oder). Es gibt keinen Grund, eine Part-Konvention zu berücksichtigen,false
die näher an 0 liegt alstrue
.Weil die Mathematik funktioniert.
Traditionell haben C-Programme Bedingungen wie
eher, als
weil der Begriff der Null gleichbedeutend mit falsch ist, ist gut verstanden.
quelle
Wie andere gesagt haben, stand die Mathematik an erster Stelle. Deshalb ist 0
false
und 1 isttrue
.Über welche Mathematik reden wir? Boolesche Algebren, die aus der Mitte des 19. Jahrhunderts stammen, lange bevor digitale Computer hinzukamen.
Man könnte auch sagen, dass die Konvention aus der Aussagenlogik hervorgegangen ist , die sogar älter ist als die Booleschen Algebren. Dies ist die Formalisierung vieler logischer Ergebnisse, die Programmierer kennen und lieben (
false || x
gleichx
,true && x
gleichx
und so weiter).Grundsätzlich geht es um das Rechnen an einer Menge mit zwei Elementen. Denken Sie darüber nach, in Binärform zu zählen. Boolesche Algebren sind der Ursprung dieses Konzepts und seiner theoretischen Grundlage. Die Konventionen von Sprachen wie C sind nur eine einfache Anwendung.
quelle
true = 1
. Das ist nicht ganz genau, denntrue != 0
das ist nicht genau dasselbe. Ein Grund (nicht der einzige), warum man Vergleiche wie vermeiden sollteif(something == true) { ... }
.Ich dachte, das hat mit der "Vererbung" von Elektronik und auch mit der Booleschen Algebra zu tun
0
=off
,negative
,no
,false
1
=on
,positive
,yes
,true
strcmp gibt 0 zurück, wenn die Zeichenfolgen gleich sind. Dies hat mit seiner Implementierung zu tun, da tatsächlich der "Abstand" zwischen den beiden Zeichenfolgen berechnet wird. Dass 0 zufällig auch als falsch angesehen wird, ist nur ein Zufall.
Die Rückgabe von 0 bei Erfolg ist sinnvoll, da 0 in diesem Fall keinen Fehler bedeutet und jede andere Zahl ein Fehlercode wäre. Die Verwendung einer anderen Nummer für den Erfolg ist weniger sinnvoll, da Sie nur einen einzigen Erfolgscode haben, während Sie mehrere Fehlercodes haben können. Sie verwenden "Hat es funktioniert?" Als if-Anweisung wäre ein Ausdruck mit 0 = yes sinnvoller, aber der Ausdruck ist korrekter. "Ist etwas schief gelaufen?" und dann sehen Sie, dass 0 = nein viel Sinn macht. Denken
false/true
macht hier nicht wirklich Sinn, wie es eigentlich istno error code/error code
.quelle
0
dass diessuccess/no error
das einzige ist, was Sinn macht, wenn andere Ganzzahlen Fehlercodes darstellen. Das ist0
auchfalse
in anderen Fällen nicht wirklich wichtig, da wir hier überhaupt nicht über wahr oder falsch sprechen;)strcmp()
Berechnung der Entfernung ist ziemlich gut. Wenn sie aufgerufen worden war ,strdiff()
dannif (!strdiff())
wäre sehr logisch.Wie in diesem Artikel erläutert , sollten die Werte
false
undtrue
nicht mit den Ganzzahlen 0 und 1 verwechselt werden, sondern können mit den Elementen des Galois-Feldes (endliches Feld) zweier Elemente (siehe hier ) identifiziert werden .Ein Feld ist eine Menge mit zwei Operationen, die bestimmte Axiome erfüllen.
Die Symbole 0 und 1 werden herkömmlicherweise verwendet, um die additiven und multiplikativen Identitäten eines Feldes zu bezeichnen, da die reellen Zahlen auch ein Feld (aber kein endliches) sind, dessen Identitäten die Nummern 0 und 1 sind.
Die additive Identität ist das Element 0 des Feldes, so dass für alle x:
und die multiplikative Identität ist das Element 1 des Feldes, so dass für alle x:
Das endliche Feld zweier Elemente hat nur diese beiden Elemente, nämlich die additive Identität 0 (oder
false
) und die multiplikative Identität 1 (odertrue
). Die beiden Operationen dieses Feldes sind das logische XOR (+) und das logische AND (*).Hinweis. Wenn Sie die Operationen umkehren (XOR ist die Multiplikation und AND ist die Addition), ist die Multiplikation nicht über die Addition verteilt und Sie haben kein Feld mehr. In einem solchen Fall haben Sie keinen Grund, die beiden Elemente 0 und 1 (in beliebiger Reihenfolge) aufzurufen. Beachten Sie auch, dass Sie nicht die Operation OR anstelle von XOR wählen können: Unabhängig davon, wie Sie OR / AND als Addition / Multiplikation interpretieren, ist die resultierende Struktur kein Feld (nicht alle inversen Elemente existieren gemäß den Feldaxiomen).
Zu den C-Funktionen:
strcmp
berechnet die Funktion die Differenz zwischen zwei Zeichenfolgen. 0 bedeutet, dass zwischen zwei Strings kein Unterschied besteht, dh dass zwei Strings gleich sind.Die obigen intuitiven Erklärungen können helfen, sich an die Interpretation der Rückgabewerte zu erinnern, aber es ist noch einfacher, nur die Bibliotheksdokumentation zu überprüfen.
quelle
Sie sollten berücksichtigen, dass alternative Systeme auch akzeptable Entwurfsentscheidungen sein können.
Shells: 0 Exit-Status ist wahr, ungleich Null ist falsch
Das Beispiel für Shells, die den Ausgangsstatus 0 als wahr behandeln, wurde bereits erwähnt.
Das Grundprinzip ist, dass es einen Weg zum Erfolg gibt, aber viele Wege zum Scheitern. Daher ist es pragmatisch, 0 als speziellen Wert zu verwenden, der "keine Fehler" bedeutet.
Ruby: 0 ist genau wie jede andere Zahl
Unter "normalen" Programmiersprachen gibt es einige Ausreißer wie Ruby, die 0 als echten Wert behandeln.
Das Grundprinzip ist, dass nur
false
undnil
sollte falsch sein. Für viele Ruby-Neulinge ist es ein Gotcha. In einigen Fällen ist es jedoch schön, dass 0 wie jede andere Zahl behandelt wird.Ein solches System funktioniert jedoch nur in einer Sprache, die Boolesche Werte als separaten Typ von Zahlen unterscheiden kann. In den früheren Tagen des Rechnens hatten Programmierer, die mit Assemblersprache oder unformatierter Maschinensprache arbeiteten, keinen solchen Luxus. Es ist wahrscheinlich nur natürlich, 0 als "leeren" Zustand zu behandeln und ein Bit auf 1 als Flag zu setzen, wenn der Code feststellt, dass etwas passiert ist. In der Folge entwickelte sich die Konvention, dass Null als falsch behandelt wurde und Nicht-Null-Werte als wahr behandelt wurden. Das muss aber nicht so sein.
Java: Zahlen können überhaupt nicht als Boolesche Werte behandelt werden
In Java
true
undfalse
sind die einzigen booleschen Werte. Zahlen sind keine Booleschen Werte und können nicht einmal in Boolesche Werte umgewandelt werden ( Java-Sprachspezifikation, Abschnitt 4.2.2 ):Diese Regel vermeidet nur die Frage insgesamt - alle booleschen Ausdrücke müssen explizit im Code geschrieben werden.
quelle
if (thing === 0)
, das ist einfach nicht cool.0
isttrue
(wie jede andere ganze Zahl) in einer dynamischen Sprache. Ich habe manchmal einen gefangen,0
als ich versuchte,None
in Python zu fangen , und das kann manchmal ziemlich schwer zu erkennen sein.if [ 0 ] ; then echo this executes ; fi
. Der falsche Datenwert ist eine leere Zeichenfolge, und eine überprüfbare Falschheit ist ein fehlgeschlagener Beendigungsstatus eines Befehls, der durch einen Wert ungleich Null dargestellt wird.Bevor wir uns mit dem allgemeinen Fall befassen, können wir Ihre Gegenbeispiele besprechen.
String-Vergleiche
Das Gleiche gilt für viele Arten von Vergleichen. Solche Vergleiche berechnen einen Abstand zwischen zwei Objekten. Wenn die Objekte gleich sind, ist der Abstand minimal. Also , wenn der „Vergleich erfolgreich“, ist der Wert 0. Aber wirklich, von dem Rückgabewert
strcmp
ist nicht ein boolean, es ist ein Abstand ist, und dass das, was Fallen nicht bewusst Programmierer tunif (strcmp(...)) do_when_equal() else do_when_not_equal()
.In C ++ könnten wir neu designen
strcmp
, um einDistance
Objekt zurückzugeben, das überschreibtoperator bool()
, um true zurückzugeben, wenn 0 (aber Sie würden dann von einer anderen Menge von Problemen gebissen werden). Oder haben Sie in einfachem C nur einestreq
Funktion, die 1 zurückgibt, wenn Zeichenfolgen gleich sind, und sonst 0.API-Aufrufe / Programm-Exit-Code
Hier kümmert es Sie, warum etwas schief gelaufen ist, weil dies die Entscheidungen auf Fehler treibt. Wenn die Dinge gelingen, möchten Sie nichts Bestimmtes wissen - Ihre Absicht wird verwirklicht. Der Rückgabewert muss daher diese Information übermitteln. Es ist kein Boolescher Wert, sondern ein Fehlercode. Der spezielle Fehlerwert 0 bedeutet "kein Fehler". Der Rest des Bereichs stellt lokal bedeutsame Fehler dar, mit denen Sie sich befassen müssen (einschließlich 1, was häufig "nicht spezifizierter Fehler" bedeutet).
Allgemeiner Fall
Dies wirft die Frage auf: Warum werden Boolesche Werte
True
undFalse
gewöhnlich mit 1 bzw. 0 dargestellt?Nun, neben dem subjektiven Argument "Es fühlt sich auf diese Weise besser an" gibt es hier ein paar Gründe (auch subjektiv), die mir einfallen:
Stromkreisanalogie. Der Strom ist für 1s EIN und für 0s AUS. Ich mag es, (1, Ja, Wahr, Ein) zusammen zu haben und (0, Nein, Falsch, Aus), anstatt eine andere Mischung
Speicherinitialisierungen. Wenn ich
memset(0)
eine Reihe von Variablen (z. B. Ints, Floats, Bools) habe, möchte ich, dass ihr Wert den konservativsten Annahmen entspricht. ZB ist meine Summe anfänglich 0, das Prädikat ist Falsch usw.Vielleicht hängen all diese Gründe mit meiner Ausbildung zusammen - wenn mir von Anfang an beigebracht worden wäre, 0 mit True zu assoziieren, würde ich den umgekehrten Weg einschlagen.
quelle
bool
.int
bisbool
in vielen Programmiersprachen. Das Vergleichs- und Fehlergestenmaterial ist nur ein Beispiel für Orte, an denen es sinnvoll gewesen wäre, es auf eine andere Weise als derzeit auszuführen.Aus einer übergeordneten Perspektive sprechen Sie von drei recht unterschiedlichen Datentypen:
Ein Boolescher. Die mathematische Konvention in der Booleschen Algebra lautet 0 für
false
und 1 fürtrue
, daher ist es sinnvoll, dieser Konvention zu folgen. Ich denke, dass dieser Weg auch intuitiver Sinn macht.Das Ergebnis des Vergleichs. Dies hat drei Werte:
<
,=
und>
( man beachte , dass keiner von ihnen isttrue
). Für sie ist es sinnvoll, die Werte -1, 0 bzw. 1 (oder allgemeiner einen negativen Wert, Null und einen positiven Wert) zu verwenden.Wenn Sie auf Gleichheit prüfen möchten und nur eine Funktion haben, die einen allgemeinen Vergleich durchführt, sollten Sie dies meines Erachtens mit etwas wie explizit machen
strcmp(str1, str2) == 0
. Ich finde die Verwendung!
in dieser Situation verwirrend, da ein nicht-boolescher Wert so behandelt wird, als wäre er ein boolescher Wert.Denken Sie auch daran, dass Vergleich und Gleichheit nicht dasselbe sein müssen. Wenn Sie beispielsweise Personen nach ihrem Geburtsdatum bestellen,
Compare(me, myTwin)
sollten Sie zurückkehren0
,Equals(me, myTwin)
sollten aber zurückkehrenfalse
.Der Erfolg oder Misserfolg einer Funktion, möglicherweise auch mit Details zu diesem Erfolg oder Misserfolg. Wenn Sie über Windows sprechen, wird dieser Typ aufgerufen,
HRESULT
und ein Wert ungleich Null zeigt nicht unbedingt einen Fehler an. In der Tat bedeutet ein negativer Wert ein Scheitern und einen nicht negativen Erfolg. Der Erfolgswert ist sehr häufigS_OK = 0
, es kann sich aber auch beispielsweise um einenS_FALSE = 1
anderen Wert handeln.Die Verwirrung ergibt sich aus der Tatsache, dass drei logisch sehr unterschiedliche Datentypen in C und einigen anderen Sprachen als ein einziger Datentyp (eine Ganzzahl) dargestellt werden und dass Sie in einer Bedingung eine Ganzzahl verwenden können. Ich halte es jedoch nicht für sinnvoll, Boolesche Werte neu zu definieren, um die Verwendung einiger nicht-boolescher Typen unter einfacheren Bedingungen zu vereinfachen.
Denken Sie auch an einen anderen Typ, der in einer Bedingung in C häufig verwendet wird: einen Zeiger. Dort ist es natürlich, einen
NULL
Zeiger (der als dargestellt wird0
) als zu behandelnfalse
. Wenn Sie also Ihrem Vorschlag folgen, wird das Arbeiten mit Zeigern ebenfalls schwieriger. (Ich persönlich bevorzuge jedoch den expliziten Vergleich von Zeigern mit ZeigernNULL
, anstatt sie als Boolesche Werte zu behandeln.)quelle
Null kann falsch sein, da die meisten CPUs ein ZERO-Flag haben, das zum Verzweigen verwendet werden kann. Es wird eine Vergleichsoperation gespeichert.
Mal sehen warum.
Einige Pseudocodes, da das Publikum Assembler wahrscheinlich nicht liest
c-source simple loop calls wibbeln 10 mal
Einige tun so, als würden sie sich versammeln
c-source ruft eine andere einfache Schleife 10 Mal wibble auf
einige so tun, als Montage für diesen Fall
etwas mehr c Quelle
und die Versammlung
Mal sehen, wie kurz das ist?
etwas mehr c Quelle
und die Assembly (nehmen wir einen marginal intelligenten Compiler an, der == 0 ohne Vergleich ersetzen kann)
Versuchen wir nun eine Konvention von true = 1
etwas mehr c source #define TRUE 1 int foo = TRUE; if (foo == TRUE) wibble ()
und die Versammlung
sehen, wie kurz der Fall mit ungleich Null wahr ist?
Wirklich frühe CPUs hatten kleine Flaggensätze am Akkumulator.
Um zu überprüfen, ob a> b oder a = b ist, wird im Allgemeinen eine Vergleichsanweisung verwendet.
Lassen Sie uns das noch einmal wiederholen. Auf einigen älteren CPUs mussten Sie keinen Vergleichsbefehl für einen Akku gleich NULL oder einen Akku kleiner als Null verwenden.
Sehen Sie jetzt, warum Null falsch sein könnte?
Bitte beachten Sie, dass dies ein Pseudocode ist und kein richtiger Befehlssatz so aussieht. Wenn Sie Assembler kennen, wissen Sie, dass ich hier vieles vereinfache. Wenn Sie etwas über das Compiler-Design wissen, mussten Sie diese Antwort nicht lesen. Jeder, der etwas über das Abrollen von Schleifen oder die Vorhersage von Verzweigungen weiß, ist in der fortgeschrittenen Klasse in Raum 203 im Flur.
quelle
if (foo)
undif (foo != 0)
sollte den gleichen Code erzeugen, und zweitens, Sie zeigen , dass die Assemblersprache Sie in der Tat mit bist hat explizite boolean Operanden und Tests für sie. Zum Beispieljz
bedeutetjump if zero
. Mit anderen Wortenif (a == 0) goto target;
. Und die Menge wird nicht einmal direkt getestet; Die Bedingung wird in ein Boolesches Flag umgewandelt, das in einem speziellen Maschinenwort gespeichert ist. Es ist eigentlich eher wiecpu.flags.zero = (a == 0); if (cpu.flags.zero) goto target;
jz
Anweisung hat, aber keinejnz
? (oder eine andere asymmetrische Reihe von bedingten Anweisungen)Es gibt viele Antworten, die darauf hindeuten, dass die Übereinstimmung zwischen 1 und wahr durch eine mathematische Eigenschaft erforderlich ist. Ich kann keine solche Immobilie finden und schlage vor, dass es sich um eine rein historische Konvention handelt.
Bei einem Feld mit zwei Elementen haben wir zwei Operationen: Addition und Multiplikation. Wir können boolesche Operationen in diesem Feld auf zwei Arten abbilden:
Traditionell identifizieren wir True mit 1 und False mit 0. Wir identifizieren AND mit * und XOR mit +. Somit ist OR eine Sättigungsaddition.
Genauso einfach können wir jedoch True mit 0 und False mit 1 identifizieren. Dann identifizieren wir OR mit * und XNOR mit +. Somit ist AND eine Sättigungsaddition.
quelle
Merkwürdigerweise ist Null nicht immer falsch.
Insbesondere ist die Unix- und Posix-Konvention
EXIT_SUCCESS
als 0 (undEXIT_FAILURE
als 1) zu definieren . Eigentlich ist es sogar eine Standard- C-Konvention !Für Posix-Shells und exit (2) -Syscalls bedeutet 0 also "erfolgreich", was intuitiv eher wahr als falsch ist.
Insbesondere
if
möchte die Shell, dass eine ProzessrückgabeEXIT_SUCCESS
(dh 0) der "then" -Verzweigung folgt!In Schema (aber nicht in Common Lisp oder in MELT ) sind 0 und nil (dh
()
in Schema) wahr, da der einzige falsche Wert ist#f
Ich bin damit einverstanden, ich nicke!
quelle
C wird für die Low-Level-Programmierung in der Nähe der Hardware verwendet. In diesem Bereich müssen Sie manchmal zwischen bitweisen und logischen Operationen für dieselben Daten wechseln. Wenn Sie einen numerischen Ausdruck nur zur Durchführung eines Tests in einen booleschen Ausdruck konvertieren müssen, wird der Code unübersichtlich.
Sie können Dinge schreiben wie:
eher, als
In einem isolierten Beispiel ist es nicht so schlimm, aber das zu tun wird lästig.
Ebenso umgekehrte Operationen. Es ist nützlich, wenn das Ergebnis einer booleschen Operation wie ein Vergleich nur eine 0 oder 1 ergibt: Angenommen, wir möchten das dritte Bit eines Wortes basierend darauf setzen, ob
modemctrl
der Träger das Bit erkennt:Hier müssen wir das, haben
!= 0
, um das Ergebnis des biweisen&
Ausdrucks auf0
oder zu reduzieren1
, aber da das Ergebnis nur eine Ganzzahl ist, müssen wir keine lästigen Casts hinzufügen, um Boolean in Ganzzahl umzuwandeln.Obwohl modernes C jetzt einen
bool
Typ hat, behält es die Gültigkeit von Code wie diesem bei, sowohl weil es eine gute Sache ist, als auch wegen des massiven Bruchs mit der Abwärtskompatibilität, der sonst verursacht würde.Ein weiteres Beispiel, in dem C glatt ist: Testen von zwei Booleschen Bedingungen als Vier-Wege-Schalter:
Sie könnten dies dem C-Programmierer nicht ohne einen Kampf nehmen!
Schließlich dient C manchmal als eine Art Assemblersprache auf hoher Ebene. In Assemblersprachen gibt es auch keine Booleschen Typen. Ein Boolescher Wert ist nur ein Bit oder ein Wert von Null gegen einen Wert ungleich Null in einem Speicherort oder Register. Eine Ganzzahl Null, eine Boolesche Null und die Adresse Null werden in Assembler-Befehlssätzen (und möglicherweise sogar Gleitkomma Null) auf dieselbe Weise getestet. Die Ähnlichkeit zwischen C und Assembler-Sprache ist nützlich, wenn beispielsweise C als Zielsprache für die Kompilierung einer anderen Sprache verwendet wird (auch einer, die stark typisierte Boolesche Sprachen hat!).
quelle
Ein Boolescher Wert oder Wahrheitswert hat nur 2 Werte. Richtig und falsch.
Diese sollten nicht als ganze Zahlen dargestellt werden, sondern als Bits (0 und 1).
Es ist verwirrend zu sagen, dass eine andere Ganzzahl neben 0 oder 1 nicht falsch ist. Wahrheitstabellen befassen sich mit Wahrheitswerten, nicht mit ganzen Zahlen.
Ausgehend von einer prospektiven Wahrheitswertigkeit würde -1 oder 2 alle Wahrheitstabellen und jede damit verbundene boolesche Logik brechen.
Die meisten Sprachen haben normalerweise einen
boolean
Typ, der, wenn er in einen Zahlentyp wie eine Ganzzahl umgewandelt wird, false als Ganzzahlwert 0 ausgibt.quelle
TRUE
oder geworfen werdenFALSE
. Niemals habe ich gesagt - vielleicht habe ich es getan, aber es war nicht beabsichtigt - Ganzzahlen waren wahr oder falsch. Ich fragte, warum sie bei der Umwandlung in einen Booleschen Wert für den jeweiligen Wert ausgewertet werden.Letztendlich geht es darum, die Kernsprache zu brechen, weil einige APIs beschissen sind. Crappy APIs sind nicht neu, und Sie können sie nicht beheben, indem Sie die Sprache brechen. Es ist eine mathematische Tatsache, dass 0 falsch und 1 wahr ist, und jede Sprache, die dies nicht beachtet, ist grundsätzlich gebrochen. Der Drei-Wege-Vergleich ist eine Nische und hat nichts damit zu tun, dass das Ergebnis implizit in konvertiert wird,
bool
da drei mögliche Ergebnisse zurückgegeben werden. Die alten C-APIs haben einfach eine schreckliche Fehlerbehandlung und sind auch überfordert, da C nicht über die erforderlichen Sprachfunktionen verfügt, um keine schrecklichen Schnittstellen zu haben.Beachten Sie, dass ich das nicht für Sprachen sage, die keine implizite Ganzzahl-> Boolesche Konvertierung haben.
quelle
+
Symbol OR bezeichnet. Also zum Beispielabc + a'b'c
bedeutet(a and b and c) or (a and (not b) and (not c))
.