Bitweises ODER vs Hinzufügen von Flags

16

Ich habe schon andere gesehen, die Bitwise-OR verwenden, um Flags zu kombinieren:

#define RUN 0x01
#define JUMP 0x02
#define SHOOT 0x04

const byte madPerson = RUN | JUMP | SHOOT;

So mache ich es auch.

Aber ich habe auch einige (nicht so viele) kombinierte Flags mit Addition gesehen:

#define RUN 0x01
#define JUMP 0x02
#define SHOOT 0x04

const byte madPerson = RUN + JUMP + SHOOT;

Welches ist "lesbarer"? (Welche werden Ihrer Meinung nach mehr Menschen erkennen?) Was ist die "Standard" -Methode, um dies zu tun? Welches bevorzugen Sie?

Mateen Ulhaq
quelle
Dies ist eine SO-Frage. Betrachten Sie mit so etwas wie 1<<0, 1<<1, 1<<2, und so weiter. Wenn Sie viele Flags haben, wird es besser lesbar, leichter zu warten und weniger fehleranfällig. Wenn Sie beispielsweise alle 64-Bit-Werte eines 64-Bit-Inters packen, möchten Sie Tippfehler unbedingt vermeiden :) Auch Ihre Darstellung 1ist wichtig. Für eine 64-Bit-Ganzzahl in VS2010 denke ich, ist es 1UI64oder so ähnlich. Die Verwendung eines falschen Typs könnte Sie beißen.
Job
3
@Job: Keine StackOverflow-Frage, da es um Lesbarkeit, Erkennbarkeit, Einstellungen und Best Practices geht. Keine einzige objektive Antwort dafür; es gehört hierher.
Macneil

Antworten:

34

Bitweises ODER.

Der Zusatz ist gefährlich.

Stellen Sie sich ein Beispiel vor, bei dem ein Bandit eine Person ist und ein wütender Bandit ein Bandit, der spricht und schießt. Später entscheiden Sie, dass alle Banditen schießen sollen, aber Sie haben die Definition der wütenden Banditen vergessen und entfernen die Schießfahne nicht.

#define PERSON 1 << 0
#define SPEAKS 1 << 1
#define SHOOTS 1 << 2
#define INVINCIBLE 1 << 3
const byte bandit = PERSON | SHOOTS;                    // 00000101
const byte angryBandit_add = bandit + SPEAKS + SHOOTS;  // 00001011 error
const byte angryBandit_or = bandit | SPEAKS | SHOOTS;   // 00000111 ok

Wenn du angryBandit_adddein Spiel benutzt hättest du jetzt den verwirrenden logischen Fehler, wütende Banditen zu haben, die nicht schießen oder getötet werden können.

Wenn Sie angryBandit_ordas Schlimmste verwendet hätten, wäre es eine Redundanz | SHOOTS.

Aus ähnlichen Gründen ist bitweises NICHT sicherer als Subtraktion zum Entfernen von Flags.

doppelgreener
quelle
11

Bitweises ODER vermittelt die Absicht klarer

Bitweises ODER sollte effizienter sein

Steven A. Lowe
quelle
+1 in der Tat denke ich auch, dass OR es klarer macht, dass es sich um Flags handelt, aber was die Effizienz betrifft, gibt es Sprachen, in denen bitweise Operationen langsam sind, z.
Ivo Wetzel
1
In Anbetracht des Beispiels des OP glaube ich nicht, dass eine Zeile von ORs oder Additionen die Ausführungsgeschwindigkeit eines Programms nachteilig beeinflussen wird.
der Blechmann
1
@ Greg: Zumal die Berechnung in diesem Beispiel zur Kompilierungszeit durchgeführt wird. :-)
Carson63000
Zusätzlich zur Vermittlung der Absicht ist es ziemlich üblich, dies in vielen Sprachen zu sehen, einschließlich, aber nicht beschränkt auf ADA, C #, Java ...
Ken Henderson
2
"sollte" ist ein sehr großes Wort in diesem Geschäft. Obwohl es sehr unwahrscheinlich ist, dass Sie auf dieses Problem heute stoßen, habe ich sehr klare Erinnerungen an die Arbeit an einem Prozessor, der keine bitweise ODER-Anweisung hatte. Sie könnten bitweise UND in einer Anweisung und bitweise XOR in einer Anweisung, aber bitweise ODER in zwei Anweisungen: ein unmittelbares bitweises UND zum Deaktivieren des Bits und ein unmittelbares bitweises XOR zum Ergänzen des neu gelöschten Bits , das hat es natürlich eingestellt.
John R. Strohm