Informatik unterschied && und & + unterscheid | und ||?

6 Antworten

&&: Logisches Und. Damit kannst du zwei Ausdrücke verknüpfen. Diese Verknüpfungsoperation liefert einen Rückgabewert (true/false). Dieser ist nur true, falls alle Teiloperationen true sind. Ist eine davon falsch, wird der Ausdruck sofort verlassen, da er nicht mehr true werden kann.

||: Logisches Oder. Das Analogon zum logischen Und. Dabei ist der Ausdruck true, sobald mindestens ein Teilausdruck true ist.

&: Bitweises Und. Dabei werden alle Teilausdrücke verknüpft:

int a = 6; // binär: 110
int b = 4; // binär: 100

int res = a & b;
// 110
// & 100
// ------
// 100

Wie du oben sehen kannst, werden die Teilausdrücke in die Binärdarstellung umgewandelt. Dabei wird jede Ziffer einzeln mit der zugehörigen verglichen (bitweise). Zwei Einsen ergeben true, also eine 1, alles andere eine Null.

Sind die Teilausdrücke keine Integer, sondern Booleans, dann verhält es sich genauso wie das logische Und, nur dass der komplette Ausdruck ausgewertet wird, auch wenn bereits ein Teilergebnis false ergeben hat.

|: Bitweises Oder. Das Analogon zum bitweisen Und. Allerdings ist dabei der Ausdruck true, sobald mindestens eine der beiden Ziffern true ist.

Sind die Teilausdrücke keine Integer, sondern Booleans, dann verhält es sich genauso wie das logische Oder, nur dass der komplette Ausdruck ausgewertet wird, auch wenn bereits ein Teilergebnis true ergeben hat.

Um auch die anderen Operatoren anzusprechen:

^: Bitweises XOR (exclusive or). D.h. genau eine der beiden Ziffern ist eine Eins.

!: logisches Nicht. D.h. der Ausdruck wird negiert.

40

||: Logisches Oder. Das Analogon zum logischen Und. Dabei ist der Ausdruck true, sobald mindestens ein Teilausdruck true ist.

Nur der Vollständigkeit halber: Bei || bricht ebenfalls die Auswertung ab, nämlich dann, wenn der linke Operand true ist.

1

In C-ähnlichen Sprachen (C, C++, Java, C-Sharp, ...) sind &&, sowie || so genannte Operatoren mit Shortcut, d. h. bei ...

a || b

... wird der rechte Ausdruck (b) nur dann ausgewertet, wenn der linke Ausdruck (a) == false ergeben hat.

Umgekehrt, bei ...

a && b

... wird der rechte Ausdruck (b) nur dann ausgewertet, wenn der linke Ausdruck (a) == true ergeben hat.

Das macht vor allem dann einen Unterschied, wenn die Auswertung eines Ausdrucks Nebeneffekte hat, z. B. ...

(a++ != 0) && (b++ != 0)

... hier wird b nur dann inkrementiert, wenn a != 0 war (vor dem Inkrementieren), a wird aber immer inkrementiert.

Bei ...

(a++ != 0) & (b++ != 0)

... würden in jedem Fall sowohl a, als auch b inkrementiert.

Ich sehe daher (sofern möglich) grundsätzlich von der Verwendung von Shortcut-Operatoren ab.

Manche Sprachen erlauben leider ausschließlich Bool'sche Operatoren mit Shortcut, z. B. Go. Aber auch hier kann man die Statements so anordnen, dass keine Fallunterscheidung stattfindet, z. B. indem man den Bool'schen Audruck zunächst in eine lokale Variable auswertet und dann anschließend die lokalen Variablen per logischen Operationen verknüpft. Dann mussten die Ausdrücke auf jeden Fall ausgewertet werden, weil die Ergebnisse ja lokalen Variablen zugewiesen wurden.

Wenn ich eine bedingte Auswertung bewirken möchte, dann schreibe ich eine explizite Verzweigung. Dann sieht wenigstens jeder, dass hier eine Fallunterscheidung stattfindet und dass ich diese auch beabsichtigt hatte.

Zudem können && und || ausschließlich mit Wahrheitswerten (booleans) arbeiten, während & und | auch Integer-Werte bitweise verknüpfen können, was z. B. bei der Generierung von Bitmasken, Implementierung von Schieberegistern, Umwandlung von Zahlen in Binärdarstellung und so weiter und so fort hilfreich sein kann.

54

Ich sehe daher (sofern möglich) grundsätzlich von der Verwendung von Shortcut-Operatoren ab.

Ich würde eher grundsätzlich Nebeneffekte in Bedingungen mit Shortcuts vermeiden. Bei Verwendung von bitweisen Operatoren stattdessen würde ich bei späterem Lesen erstmal denken, dass ich ein Zeichen vergessen hätte.  

1
40
@Machtnix53

Ich würde eher grundsätzlich Nebeneffekte in Bedingungen mit Shortcuts vermeiden.

Das ist natürlich noch besser.

Bei Verwendung von bitweisen Operatoren stattdessen würde ich bei späterem Lesen erstmal denken, dass ich ein Zeichen vergessen hätte.

Es gibt aber auch einen weiteren Unterschied.

Nachdem die Auswertung des "rechten Arguments" bei && bzw. || bedingt erfolgt, wird der Compiler eine zusätzliche conditional branch instruction erzeugen - zusätzlich zu der, die durch die if-Abfrage (in der diese Operatoren sehr wahrscheinlich eingebettet sind) vorkommt, d. h. es gibt letztlich mehr Maschineninstruktionen abzuarbeiten und mehr Möglichkeiten für die branch prediction des Prozessors, daneben zu liegen und einen pipeline flush auszulösen. Der Laufzeitunterschied ist sicher nicht sehr signifikant, aber ggf. messbar.

Bei C sehe ich ein Problem, weil es keinen dezidierten Boolean-Datentyp gibt. Von daher sind & und | im Zusammenhang mit Bool'schen Ausdrücken unter umständen "missverständlich" (führen zu anderen Ergebnissen, als && und ||). Bei Java gibt es dieses Problem eher nicht.

1

Den einfachen & bzw. einfachen | gibt es auch logisch (und nicht nur bitweise, wie man nach obigen Antworten denken könnte).

Sind a() und b() Funktionen (oder komplexere Ausdrücke) mit booleschem Resultat, dann bedeutet

a() & b(),

dass zuerst a() ausgewertet wird, dann wird b() ausgewertet und am Schluss wird das logische "und" der beiden booleschen Resultate genommen (Analog | für oder).

Hingegen bedeutet

a() && b(),

dass b() nicht ausgewertet wird, wenn die Funktion a() bereits "false" liefert. WICHTIG: Der Aufruf der Funktion b() wird bei && evtl. gespart, wohingegen beim alleinigen & die Funktion b() IMMER aufgerufen wird, auch wenn a() false ist!

Man bezeichnet darher &&  (und ||) auch als "Abkürzungsoperatoren" (Shortcut-evaluation).

Alles klar?

PS: Das einfache & (bzw. |) wird sehr selten für logische Zusammensetzung benötigt, da es zum einen langsamer ist und meistens b() tatsächlich irrelevant ist, wenn die Aussage bereits aus a() errechnet werden kann. Es gibt jedoch seltene Ausnahmen, wenn der User z. B. beides gefragt werden muss (a() und b()), wenn eine Subroutine Nebeneffekte aufweist.

vornameEingabeOK() & mailEingabeOK()

Was möchtest Du wissen?