108 Stimmen

Bitweise Operatoren für Boolesche Operatoren in C++ verwenden

Gibt es einen Grund, die bitweisen Operatoren &, | und ^ für "bool"-Werte in C++ nicht zu verwenden?

Manchmal stoße ich auf Situationen, in denen ich möchte, dass genau eine von zwei Bedingungen wahr ist (XOR), also füge ich einfach den Operator ^ in einen bedingten Ausdruck ein. Manchmal möchte ich auch, dass alle Teile einer Bedingung ausgewertet werden, unabhängig davon, ob das Ergebnis wahr ist oder nicht (anstelle eines Kurzschlusses), daher verwende ich & und |. Manchmal muss ich auch boolesche Werte akkumulieren, wobei &= und |= sehr nützlich sein können.

Ich habe ein paar hochgezogene Augenbrauen bekommen, als ich dies tat, aber der Code ist immer noch sinnvoll und sauberer als er es sonst wäre. Gibt es einen Grund, diese nicht für bools zu verwenden? Gibt es moderne Compiler, die in diesem Fall schlechte Ergebnisse liefern?

0 Stimmen

Wenn Sie seit dem Stellen dieser Frage ausreichend viel über C++ gelernt haben, sollten Sie zurückkommen und die aktuelle Antwort zurücknehmen und die Antwort von Patrick Johnmeyer akzeptieren, da sie den Unterschied zwischen Kurzschlüssen korrekt erklärt.

0 Stimmen

Allgemeine Bemerkung, weil die Leute sich fragen, ob dies eine gute Idee ist. Wenn man sich um die Verzweigungsabdeckung von Unit-Tests kümmert, dann ist eine Reduzierung der Verzweigungen wünschenswert. Bitweise Operatoren sind dafür nützlich.

3voto

bk1e Punkte 23191

Im Gegensatz zu Patricks Antwort hat C++ keine ^^ Operator zur Durchführung eines Kurzschlusses exklusiv oder. Wenn Sie eine Sekunde darüber nachdenken, ist ein ^^ Operator würde ohnehin keinen Sinn machen: bei exklusivem oder hängt das Ergebnis immer von beiden Operanden ab. Allerdings ist Patricks Warnung vor nicht- bool "Boolesche" Typen gelten auch beim Vergleich 1 & 2 a 1 && 2 . Ein klassisches Beispiel hierfür ist die Windows GetMessage() Funktion, die einen dreistufigen BOOL : ungleich Null, 0 o -1 .

Verwendung von & anstelle von && y | anstelle von || ist kein ungewöhnlicher Tippfehler, und wenn Sie ihn absichtlich machen, sollten Sie auch sagen, warum.

7 Stimmen

A ^^ wäre unabhängig von der Berücksichtigung des Kurzschlusses immer noch nützlich. Er würde a) die Operanden in einem booleschen Kontext auswerten und b) garantiert eine 1 oder 0 zurückgeben.

0 Stimmen

@CraigMcQueen. Es ist einfach zu definieren inline bool XOR(bool a,bool b) { return a!=b; } und Sie erhalten, was Sie wollen, außer dass es sich um eine Funktion und nicht um einen (Infix-)Operator handelt. Oder Sie könnten direkt verwenden != oder einen anderen Operator mit dieser Bedeutung überladen, aber dann müssen Sie natürlich sehr vorsichtig sein, um nicht versehentlich eine unbeabsichtigte Überladung mit demselben Namen zu verwenden. Und nebenbei bemerkt || y && return true o false , nicht 1 o 0 .

0 Stimmen

Und es scheint, dass die Tatsache, dass ! , || y && ihre Argumente in einem booleschen Kontext auswerten, liegt nur daran, dass diese Operatoren selten überladen werden, um andere Typen zu akzeptieren; soweit ich weiß, erlaubt die Sprache solche Überladungen und garantiert daher nicht die Auswertung von Argumenten in einem booleschen Kontext.

3voto

Anoop Menon Punkte 599

Die Verwendung bitweiser Operationen für bool hilft, dem Prozessor unnötige Verzweigungsvorhersagelogik zu ersparen, die sich aus einem 'cmp'-Befehl ergibt, der durch logische Operationen eingebracht wird.

Das Ersetzen der logischen durch bitweise Operationen (bei denen alle Operanden bool sind) erzeugt effizienteren Code, der das gleiche Ergebnis liefert. Die Effizienz sollte idealerweise alle Kurzschlussvorteile aufwiegen, die bei der Bestellung mit logischen Operationen genutzt werden können.

Dies kann den Code ein wenig unleserlich machen, obwohl der Programmierer ihn mit Gründen kommentieren sollte, warum dies so gemacht wurde.

2voto

genix Punkte 81

Patrick hat gute Argumente vorgebracht, und ich werde sie nicht wiederholen. Allerdings könnte ich vorschlagen, "if"-Anweisungen auf lesbares Englisch zu reduzieren, wo immer dies möglich ist, indem man gut benannte boolesche Variablen verwendet:

bool onlyAIsTrue = (a && !b); // you could use bitwise XOR here
bool onlyBIsTrue = (b && !a); // and not need this second line
if (onlyAIsTrue || onlyBIsTrue)
{
 .. stuff ..
}

Man könnte meinen, dass die Verwendung eines Booleschen Wertes unnötig ist, aber es gibt zwei wesentliche Vorteile:

  • Ihr Code ist leichter zu verstehen, weil der Zwischenwert für die "if"-Bedingung die Absicht der Bedingung deutlicher macht.
  • Wenn Sie nicht standardmäßigen oder unerwarteten Code verwenden, wie z. B. bitweise Operatoren für boolesche Werte, können andere viel leichter erkennen, warum Sie dies getan haben.

EDIT: Sie didnt explizit sagen, Sie wollten die Conditionals für 'if' Anweisungen (obwohl dies am wahrscheinlichsten scheint), das war meine Annahme. Aber mein Vorschlag eines booleschen Zwischenwertes bleibt bestehen.

0voto

spoulson Punkte 20898

IIRC, viele C++-Compiler warnen, wenn versucht wird, das Ergebnis einer bitweisen Operation als bool zu casten. Sie müssten einen Typ-Cast verwenden, um den Compiler zufrieden zu stellen.

Die Verwendung einer bitweisen Operation in einem if-Ausdruck würde die gleiche Kritik hervorrufen, wenn auch vielleicht nicht durch den Compiler. Jeder Wert, der nicht Null ist, wird als wahr angesehen, so dass etwas wie "if (7 & 3)" wahr sein wird. Dieses Verhalten mag in Perl akzeptabel sein, aber C/C++ sind sehr explizite Sprachen. Ich denke, die Spock'sche Augenbraue ist der Sorgfalt geschuldet :) Ich würde "== 0" oder "!= 0" anfügen, um deutlich zu machen, was Ihr Ziel war.

Aber wie auch immer, es klingt nach einer persönlichen Vorliebe. Ich würde den Code durch Lint oder ein ähnliches Tool laufen lassen und sehen, ob es auch denkt, dass es eine unkluge Strategie ist. Ich persönlich halte es für einen Programmierfehler.

0 Stimmen

Ihr Beitrag hat mich motiviert, dies zu testen und gcc hat nicht gewarnt! Schade, denn ich wollte diese Warnung benutzen, um zu rechtfertigen, dass ich &= ausführen darf, um bool-Ergebnisse zu akkumulieren, im Vertrauen darauf, dass andere die Warnung sehen würden, wenn sie später meinen Test ändern. Mein Code würde bei geraden Ganzzahlen fehlschlagen, da sie zu 0/falsch ausgewertet werden - ohne Warnungen! Zeit für ein Refactoring...

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X