Gibt es einen Unterschied zwischen JA / NEIN, WAHR / FALSCH und wahr / falsch in Ziel-c?

154

Einfache Frage wirklich; Gibt es einen Unterschied zwischen diesen Werten (und gibt es einen Unterschied zwischen BOOL und Bool)? Ein Mitarbeiter erwähnte, dass sie in Objective-C verschiedene Dinge bewerten, aber als ich mir die Typedefs in ihren jeweiligen .h-Dateien ansah, wurden YES / TRUE / true als 1und NO / FALSE / false als definiert 0. Gibt es wirklich einen Unterschied?

Kevlar
quelle
5
Aus praktischer Sicht gibt es keinen Unterschied. Sie können wahrscheinlich verschiedene Tricks ausführen, um einen Unterschied zu demonstrieren, aber Sie würden im Allgemeinen in ein Gebiet mit "undefiniertem Verhalten" abwandern.
Hot Licks

Antworten:

84

Es gibt keinen praktischen Unterschied, vorausgesetzt, Sie verwenden BOOLVariablen als Boolesche Werte. C verarbeitet boolesche Ausdrücke basierend darauf, ob sie 0 ergeben oder nicht 0. Also:

if(someVar ) { ... }
if(!someVar) { ... }

bedeutet das gleiche wie

if(someVar!=0) { ... }
if(someVar==0) { ... }

Aus diesem Grund können Sie jeden primitiven Typ oder Ausdruck als booleschen Test auswerten (einschließlich z. B. Zeiger). Beachten Sie, dass Sie das erstere tun sollten, nicht das letztere.

Beachten Sie, dass es ist ein Unterschied , ob man stumpfe Werte zu einem sogenannten zuweisen BOOLVariable und Test für bestimmte Werte, so dass immer sie als booleans verwenden und ordnen sie nur von ihren #defineWerten.

Wichtig ist, dass Sie Boolesche Werte niemals mit einem Zeichenvergleich testen - dies ist nicht nur riskant, da someVarein Wert ungleich Null zugewiesen werden kann, der nicht JA ist, sondern meiner Meinung nach, was noch wichtiger ist, die Absicht nicht richtig ausdrückt:

if(someVar==YES) { ... } // don't do this!
if(someVar==NO ) { ... } // don't do this either!

Mit anderen Worten, verwenden Sie Konstrukte so, wie sie verwendet und dokumentiert werden sollen, und Sie ersparen sich eine Welt voller Verletzungen in C.

Lawrence Dol
quelle
100

Ich glaube, es gibt einen Unterschied zwischen boolund BOOL. Auf dieser Webseite finden Sie eine Erklärung, warum:
http://iosdevelopertips.com/objective-c/of-bool-and-yes.html

Da BOOLes sich unsigned charnicht um einen primitiven Typ handelt, können Variablen des Typs BOOLandere Werte als YESund enthalten NO.

Betrachten Sie diesen Code:

BOOL b = 42;

if (b) {
    printf("b is not NO!\n");
}

if (b != YES) {
    printf("b is not YES!\n");
}

Die Ausgabe ist:

b ist nicht NEIN!
b ist nicht JA!

Für die meisten Menschen ist dies ein unnötiges Problem, aber wenn Sie wirklich einen Booleschen Wert wünschen, ist es besser, einen zu verwenden bool. Ich sollte hinzufügen: Das iOS SDK verwendet BOOLim Allgemeinen für seine Schnittstellendefinitionen, so dass dies ein Argument ist, an dem man festhalten muss BOOL.

Dan J.
quelle
5
Beachten Sie jedoch, dass die ursprüngliche C-Implementierung keine hatte bool, und daher ist es Tradition, einen intoder charals Booleschen Wert zu verwenden, manchmal mit einem #define, um den Unterschied zu verbergen, und manchmal nicht. Tatsächlich bin ich mir nicht sicher, ob selbst aktuelle Standards boolso implementiert werden müssen, dass die interne Struktur nicht überprüft werden kann.
Hot Licks
1
Obwohl der erste printfLügen erzählt. Der Wert von bist nicht YES, es ist "nicht Null", was die Bedingung testet. Also solltest du haben printf("b is not zero"), was nicht unbedingt das gleiche ist wie YES. In diesem Fall bist sowohl "nicht Null" als auch "nicht JA".
Lawrence Dol
Danke Lawrence, ich habe ein Update in diese Richtung gemacht.
Dan J
In der Tat habe ich die zweite Ausgabe in Xcode 8.2 nicht erhalten. Wo versage ich?
Igor Kislyuk
1
@HotLicks gibt es keinen inhärenten Unterschied zwischen 0, nicht Null und falsch und wahr. Solange der Wert ein logischer Boolescher Wert sein soll, verfügt er immer über diese Schnittstelle, um die Binärkompatibilität zu gewährleisten. Die Probleme beginnen, wenn Sie Nicht-Boolesche Werte verwenden, die wie Boolesche Werte erscheinen, z. B. die Standardfunktion für die Eingabe von Bibliotheksanwendungen. Main gibt bei Erfolg 0 zurück. Viele denken am Ende an diese 0 als Booleschen Wert, obwohl es sich tatsächlich um eine anwendungsdefinierte oder benutzerdefinierte Aufzählung handelt Wert, von dem Callees bei abnormaler Beendigung häufig erwarten, dass er ungleich Null ist.
Dmitry
52

Ich habe dies ausführlich getestet. Meine Ergebnisse sollten für sich selbst sprechen:

//These will all print "1"
NSLog(@"%d", true == true);
NSLog(@"%d", TRUE == true);
NSLog(@"%d", YES  == true);
NSLog(@"%d", true == TRUE);
NSLog(@"%d", TRUE == TRUE);
NSLog(@"%d", YES  == TRUE);
NSLog(@"%d", true == YES);
NSLog(@"%d", TRUE == YES);
NSLog(@"%d", YES  == YES);

NSLog(@"%d", false == false);
NSLog(@"%d", FALSE == false);
NSLog(@"%d", NO    == false);
NSLog(@"%d", false == FALSE);
NSLog(@"%d", FALSE == FALSE);
NSLog(@"%d", NO    == FALSE);
NSLog(@"%d", false == NO);
NSLog(@"%d", FALSE == NO);
NSLog(@"%d", NO    == NO);


//These will all print "0"
NSLog(@"%d", false == true);
NSLog(@"%d", FALSE == true);
NSLog(@"%d", NO    == true);
NSLog(@"%d", false == TRUE);
NSLog(@"%d", FALSE == TRUE);
NSLog(@"%d", NO    == TRUE);
NSLog(@"%d", false == YES);
NSLog(@"%d", FALSE == YES);
NSLog(@"%d", NO    == YES);

NSLog(@"%d", true == false);
NSLog(@"%d", TRUE == false);
NSLog(@"%d", YES  == false);
NSLog(@"%d", true == FALSE);
NSLog(@"%d", TRUE == FALSE);
NSLog(@"%d", YES  == FALSE);
NSLog(@"%d", true == NO);
NSLog(@"%d", TRUE == NO);
NSLog(@"%d", YES  == NO);

Die Ausgabe ist:

2013-02-19 20:30:37.061 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.061 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.072 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.073 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.073 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.074 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.074 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.075 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.075 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.076 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.077 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.077 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.078 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.078 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.079 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.079 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.080 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.080 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.081 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.081 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.082 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.091 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.092 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.093 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.093 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.094 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.094 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.095 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.095 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.096 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.096 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.097 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.098 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.101 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.102 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.102 BooleanTests[27433:a0f] 0
Supuhstar
quelle
3
[[NSObject] alloc] init] ist nicht gleich TRUE oder YES. Das Testen der Objektinitialisierung mit if ([[NSObject] alloc] init] == ​​TRUE) schlägt daher fehl. Ich war noch nie mit einer Sprache vertraut, die einen singulären "wahren" Wert definiert, obwohl tatsächlich ein Wert ungleich Null ausreicht.
DrFloyd5
3
@SamuelRenkert Ich war noch nie mit einer Sprache vertraut, die einen nicht-booleschen Wert in einem ifoder einem hat while. Wie ... while("guitar gently weeps")sollte nicht funktionieren ...
Supuhstar
@SamuelRenkert auch die Linux-Hintertür, die 2003 gefunden wurde:if (user_id = ROOT_UID)
Supuhstar
14

Vielleicht möchten Sie die Antworten auf diese Frage lesen . Zusammenfassend in Objective-C (aus der Definition in objc.h):

typedef signed char        BOOL; 
// BOOL is explicitly signed so @encode(BOOL) == "c" rather than "C" 
// even if -funsigned-char is used.
#define OBJC_BOOL_DEFINED


#define YES             (BOOL)1
#define NO              (BOOL)0
Barry Wark
quelle
11

Der Hauptunterschied (gefährlich!) Zwischen trueund YESliegt in der JSON-Serialisierung.

Zum Beispiel haben wir eine Serveranforderung vom Typ JSON und müssen true / false in json sence senden:

NSDictionary *r1 = @{@"bool" : @(true)};
NSDictionary *r2 = @{@"bool" : @(YES)};
NSDictionary *r3 = @{@"bool" : @((BOOL)true)};

Dann konvertieren wir es in eine JSON-Zeichenfolge, bevor wir es als senden

NSData *data = [NSJSONSerialization  dataWithJSONObject:requestParams options:0 error:nil];
NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

Das Ergebnis ist

jsonString1 // {"bool":1}
jsonString2 // {"bool":true}
jsonString3 // {"bool":true}

Aufgrund der API-Logik jsonString1kann dies zu einem Fehler führen.

Seien Sie also vorsichtig mit Booleschen Werten in Objective-C.

Zusammenfassend lässt sich sagen, dass nur exakte @YESund gegossene Werte @((BOOL)expression)vom __NSCFBooleanTyp sind und truemit JSON-Serialisierung konvertiert werden . Alle anderen Ausdrücke wie @(expression1 && expression2)(gerade @(YES && YES)) sind vom __NSCFNumber (int)Typ und werden 1in JSON konvertiert .

PS Sie können einfach einen Booleschen Wert mit Zeichenfolgen verwenden

@{@"bool" : @"true"}; // in JSON {"bool":true}
Malex
quelle
1

Es gibt einen subtilen Fehler, den hier niemand erwähnt hat, von dem ich dachte, ich würde ihn einschließen ... eher ein logischer Fehler als irgendetwas:

int i = 2;
if(i);        //true
if(i==YES);   // false
if((!!i)==YES); //true

Das Problem hier ist also genau das, (YES==1)und in C ist der Vergleich kein boolescher, sondern ein auf dem Wert basierender.

weil YESes nur ein #define(und nicht etwas, das der Sprache innewohnt) ist, muss es einen Wert haben und 1ist am sinnvollsten.

Grady Spieler
quelle
Dies ist im Wesentlichen die gleiche Antwort wie die von DanJ aus 2+ Jahren zuvor, mit weniger Details.
Lawrence Dol
@LawrenceDol Ich weiß nicht, es wird erwähnt, dass YES nur #defined ist, um 1 zu sein und nicht der Sprache eigen ist, wie es in einer höheren Sprache sein könnte ... jemand könnte möglicherweise Wert daraus ziehen ... aber gut Trolling mit dir.
Grady Player
0

Ich denke, sie fügen JA / NEIN hinzu, um in vielen Fällen selbsterklärender zu sein. Beispielsweise:

[button setHidden:YES];

klingt besser als

[button setHidden:TRUE];
Marco
quelle
2
Ich bin nicht einverstanden; beide lesen mir dasselbe vor. In einer Benutzeroberfläche für Laien finde ich jedoch, dass Ja / Nein besser aussieht.
Lawrence Dol
16
Ich bin auch anderer Meinung. Wenn überhaupt, liest es sich schlecht, weil es sich nicht an die ungeschriebenen Standards hält, die seit Jahren in anderen Sprachen verwendet werden. IE ist ein Paradebeispiel dafür, was passiert, wenn Sie eine große Anzahl von Standards nicht einhalten.
FreeAsInBeer
1
Halb Downvote für 2 ungenaue Antworten und halb Downvote für die Unterzeichnung Ihrer Antworten
fpg1503
-2

Lassen Sie uns zunächst untersuchen, was wahr und falsch ist und was ihnen überhaupt Bedeutung gibt.

Wir können eine Struktur konstruieren, die aufgerufen wird, wenn a dann b sonst c in der Lambda-Rechnung wie folgt ist:

(\ifThenElse. <use if then else>)(\a. \b. \c. a b c)

In JavaScript sieht dies folgendermaßen aus:

(function(ifThenElse) {
    // use ifThenElse
})(function(a) {
    return function(b) {
        return function(c) {
            return a(b)(c);
        };
    };
});

Damit ifThenElse nützlich ist, benötigen wir eine Funktion "true", die entweder rechts oder links wählt und dies unter Ignorieren der anderen Option tut, oder eine Funktion "false", die die Option "true" auswählt, nicht.

Wir können diese Funktionen wie folgt definieren:

(\true. <use true>)(\a. \b. a) and (\false. <use false>)(\a. \b. b)

In JavaScript sieht es so aus:

(function(True) {
    // use True
})(function(a) {
     return function(b) {
         return a;
     }
});

(function(False) {
    // use True
})(function(a) {
     return function(b) {
         return b;
     }
});

Jetzt können wir Folgendes tun

(\true. \false. \ifThenElse. \doThis. \doThat. ifThenElse true doThis doThat)
(\a. \b. a)(\a. \b. b)(\a. \b. \c. a b c)(\a. ())(\a. ())

Mit doThis und doThat (\ a. ()), da Lambda Calculus keine Dienste wie Drucken / Mathematik / Zeichenfolgen anbietet, können wir nur nichts tun und sagen, dass wir es getan haben (und später betrügen, indem wir es durch Dienste in ersetzen unser System, das die gewünschten Nebenwirkungen bietet)

Lassen Sie uns dies in Aktion sehen.

(function(True) {
    return (function(False) {
        return (function(ifThenElse) {
            return (function(doThis) {
                return (function(doThat) {
                    return ifThenElse(True)(doThis)(doThat);
                });
            });
        });
    })
})(function(a) {
     return function(b) {
         return a;
     }
})(function(a) {
     return function(b) {
         return b;
     }
})(function(a) {
    return function(b) {
        return function(c) {
            return a(b)(c);
        };
    };
})(function(a) { console.log("you chose LEFT!"); })
(function(a) {console.log("you chose RIGHT");})();

Das ist eine tiefe Umgebung, die vereinfacht werden könnte, wenn wir Arrays / Maps / Argumente / oder mehr als eine Anweisung verwenden könnten, um sie in mehrere Funktionen aufzuteilen, aber ich möchte sie so rein wie möglich halten, um mich auf Funktionen mit genau einem Argument zu beschränken nur.

Beachten Sie, dass der Name Wahr / Falsch keine inhärente Bedeutung hat. Wir können sie leicht in Ja / Nein, Links / Rechts, Rechts / Links, Null / Eins, Apfel / Orange umbenennen. Es ist insofern von Bedeutung, als die getroffene Wahl nur durch die Art der Wahl verursacht wird, die sie getroffen hat. Wenn also "LINKS" gedruckt wird, wissen wir, dass die Auswahl nur wahr sein kann, und basierend auf diesem Wissen können wir unsere weiteren Entscheidungen leiten.

Also um es zusammenzufassen

function ChooseRight(left) {
    return function _ChooseRight_inner(right) {
        return right;
    }
}
function ChooseLeft(left) {
    return function _ChooseLeft_inner(right) {
        return left;
    }
}

var env = {
    '0': ChooseLeft,
    '1': ChooseRight,
    'false': ChooseRight,
    'true': ChooseLeft,
    'no': ChooseRight
    'yes': ChooseLeft,
    'snd': ChooseRight,
    'fst': ChooseLeft
};
var _0 = env['0'];
var _1 = env['1'];
var _true = env['true'];
var _false = env['false'];
var yes = env['yes'];
var no = env['no'];

// encodes church zero or one to boolean
function lambda_encodeBoolean(self) {
    return self(false)(true);
}
// decodes a Boolean to church zero or one
function lambda_decodeBoolean(self) {
    console.log(self, self ? env['true'] : env['false']);
    return self ? env['true'] : env['false'];
}

lambda_decodeBoolean('one' === 'two')(function() {
    console.log('one is two');
})(function() {
    console.log('one is not two');
})();

lambda_decodeBoolean('one' === 'one')(function() {
    console.log('one is one');
})(function() {
    console.log('one is not one');
})();
Dmitry
quelle
-7

Nein, JA / NEIN ist eine andere Art, sich auf WAHR / FALSCH (1/0) zu beziehen.

Marco
quelle