Logischer Operator ( ||
und &&
) vs. bitweiser Operator ( |
und &
).
Der wichtigste Unterschied zwischen einem logischen Operator und einem bitweisen Operator besteht darin, dass ein logischer Operator zwei Boolesche Werte verwendet und einen Booleschen Wert erzeugt, während ein bitweiser Operator zwei Ganzzahlen verwendet und eine Ganzzahl erzeugt (Hinweis: Ganzzahlen bedeuten einen beliebigen integralen Datentyp, nicht nur int).
Um pedantisch zu sein, nimmt ein bitweiser Operator ein Bitmuster (z. B. 01101011) und führt ein bitweises UND / ODER für jedes Bit durch. Wenn Sie beispielsweise zwei 8-Bit-Ganzzahlen haben:
a = 00110010 (in decimal: 32+16+2 = 50)
b = 01010011 (in decimal: 64+ 16+2+1 = 83)
----------------
a & b = 00010010 (in decimal: 16+2 = 18)
a | b = 01110011 (in decimal: 64+32+16+2+1 = 115)
während ein logischer Operator nur funktioniert in bool
:
a = true
b = false
--------------
a && b = false
a || b = true
Zweitens ist es oft möglich, einen bitweisen Operator für bool zu verwenden, da true und false gleich 1 bzw. 0 sind. Wenn Sie true in 1 und false in 0 übersetzen, führen Sie eine bitweise Operation durch und konvertieren Sie dann Nicht-Null zu wahr und null zu falsch; Es kommt vor, dass das Ergebnis das gleiche ist, wenn Sie gerade einen logischen Operator verwendet haben (überprüfen Sie dies auf Übung).
Ein weiterer wichtiger Unterschied besteht darin, dass ein logischer Operator kurzgeschlossen wird . So sieht man in manchen Kreisen [1] oft Leute, die so etwas tun:
if (person && person.punch()) {
person.doVictoryDance()
}
was übersetzt bedeutet: "Wenn eine Person existiert (dh nicht null ist), versuchen Sie, sie / ihn zu schlagen, und wenn der Schlag erfolgreich ist (dh wahr zurückgibt), dann machen Sie einen Siegestanz" .
Hatten Sie stattdessen einen bitweisen Operator verwendet:
if (person & person.punch()) {
person.doVictoryDance()
}
wird übersetzt zu: "Wenn eine Person existiert (dh nicht null ist) und der Schlag erfolgreich ist (dh wahr zurückgibt), dann mache einen Siegestanz" .
Beachten Sie, dass im kurzgeschlossenen logischen Operator der person.punch()
Code möglicherweise überhaupt nicht ausgeführt wird, wenn er person
null ist. Tatsächlich würde in diesem speziellen Fall der zweite Code einen Nullreferenzfehler erzeugen, wenn er person
null ist, da er versucht aufzurufen, person.punch()
unabhängig davon, ob die Person null ist oder nicht. Dieses Verhalten, den richtigen Operanden nicht auszuwerten, wird als Kurzschluss bezeichnet .
[1] Einige Programmierer werden es ablehnen, einen Funktionsaufruf zu platzieren, der einen Nebeneffekt in einem if
Ausdruck hat, während es für andere eine übliche und sehr nützliche Redewendung ist.
Da ein bitweiser Operator jeweils mit 32-Bit arbeitet (wenn Sie sich auf einem 32-Bit-Computer befinden), kann dies zu einem eleganteren und schnelleren Code führen, wenn Sie eine große Anzahl von Bedingungen vergleichen müssen, z
int CAN_PUNCH = 1 << 0, CAN_KICK = 1 << 1, CAN_DRINK = 1 << 2, CAN_SIT = 1 << 3,
CAN_SHOOT_GUNS = 1 << 4, CAN_TALK = 1 << 5, CAN_SHOOT_CANNONS = 1 << 6;
Person person;
person.abilities = CAN_PUNCH | CAN_KICK | CAN_DRINK | CAN_SIT | CAN_SHOOT_GUNS;
Place bar;
bar.rules = CAN_DRINK | CAN_SIT | CAN_TALK;
Place military;
military.rules = CAN_SHOOT_CANNONS | CAN_PUNCH | CAN_KICK | CAN_SHOOT_GUNS | CAN_SIT;
CurrentLocation cloc1, cloc2;
cloc1.usable_abilities = person_abilities & bar_rules;
cloc2.usable_abilities = person_abilities & military_rules;
// cloc1.usable_abilities will contain the bit pattern that matches `CAN_DRINK | CAN_SIT`
// while cloc2.usable_abilities will contain the bit pattern that matches `CAN_PUNCH | CAN_KICK | CAN_SHOOT_GUNS | CAN_SIT`
Dasselbe mit logischen Operatoren zu tun, würde eine unangenehme Anzahl von Vergleichen erfordern:
Person person;
person.can_punch = person.can_kick = person.can_drink = person.can_sit = person.can_shoot_guns = true;
person.can_shoot_cannons = false;
Place bar;
bar.rules.can_drink = bar.rules.can_sit = bar.rules.can_talk = true;
bar.rules.can_punch = bar.rules.can_kick = bar.rules.can_shoot_guns = bar.rules.can_shoot_cannons = false;
Place military;
military.rules.can_punch = military.rules.can_kick = military.rules.can_shoot_guns = military.rules.can_shoot_cannons = military.rules.can_sit = true;
military.rules.can_drink = military.rules.can_talk = false;
CurrentLocation cloc1;
bool cloc1.usable_abilities.can_punch = bar.rules.can_punch && person.can_punch,
cloc1.usable_abilities.can_kick = bar.rules.can_kick && person.can_kick,
cloc1.usable_abilities.can_drink = bar.rules.can_drink && person.can_drink,
cloc1.usable_abilities.can_sit = bar.rules.can_sit && person.can_sit,
cloc1.usable_abilities.can_shoot_guns = bar.rules.can_shoot_guns && person.can_shoot_guns,
cloc1.usable_abilities.can_shoot_cannons = bar.rules.can_shoot_cannons && person.can_shoot_cannons
cloc1.usable_abilities.can_talk = bar.rules.can_talk && person.can_talk;
bool cloc2.usable_abilities.can_punch = military.rules.can_punch && person.can_punch,
cloc2.usable_abilities.can_kick = military.rules.can_kick && person.can_kick,
cloc2.usable_abilities.can_drink = military.rules.can_drink && person.can_drink,
cloc2.usable_abilities.can_sit = military.rules.can_sit && person.can_sit,
cloc2.usable_abilities.can_shoot_guns = military.rules.can_shoot_guns && person.can_shoot_guns,
cloc2.usable_abilities.can_talk = military.rules.can_talk && person.can_talk,
cloc2.usable_abilities.can_shoot_cannons = military.rules.can_shoot_cannons && person.can_shoot_cannons;
Ein klassisches Beispiel für die Verwendung von Bitmustern und bitweisen Operatoren sind Unix / Linux-Dateisystemberechtigungen.