2016-05-15 3 views
2

Ich hatte den Eindruck, dass in der C-Sprache der logische Operator || ein Kurzschlussoperator ist, der die rhs nicht auswertet, wenn die lhs falsch ist. Ich habe ein Problem beim Vergleichen von OR'ed-Werten festgestellt. Kann mir jemand erklären, warum der folgende Code (auf gcc 5.3) wahr ist? Ich bekomme das gleiche Verhalten beim Klingeln.Short Circuit Logisches ODER-Verhalten

#include <stdio.h> 

int main() { 

    int attr = 2; 

    if(((attr & 2) != 2) || ((attr & 4) != 4)) { 
     printf("No short circuit?\n"); 
    }; 

    printf("%i %i\n",attr,(attr & 2)); 

}; 

Ausgang:

No short circuit? 

2 2 
+5

Ihr Eindruck ist falsch. Wenn die LHS falsch ist, versucht es die RHS. –

+4

'das bewertet nicht die rhs, wenn die lhs falsch ist, das macht überhaupt keinen Sinn. Es ist im Gegensatz zu dem, was ein logisches ODER sein soll. Ihre Aussage gilt für logisches UND. –

+0

"* logischer ODER-Operator || ist ein Kurzschlussoperator, der die rhs nicht auswertet, wenn die lhs falsch ist *" Pause machen! ;-) – alk

Antwort

2

((attr & 2) != 2) || ((attr & 4) != 4) true ausgewertet, weil

  1. attr & 4 == 0 und (attr & 4) != 41 ist, weil attr & 4 nicht gleich 4 ist. (N1570 6.5.9 Gleichheitsoperatoren)
  2. Da mindestens einer der Operanden nicht Null ist, wird der Ausdruck 1 ausgewertet. (N1570 6.5.14 Logischer OR-Operator)
  3. Die if-Anweisung erstellt die erste Subanweisung, wenn der steuernde Ausdruck nicht null ist (N1570 6.8.4.1 Die if-Anweisung), und Sie nennen sie "den Ausdruck evaluated to true".

Logical OR-Operator nicht rhs beurteilen, ob die LHS ist wahr, da der Wert in beiden Fällen wahr sein rhs wahr oder falsch ist.

Logische AND Operator wird RH nicht bewerten, wenn die LHs falsch ist, weil der Wert in beiden Fällen false ist die RHS ist wahr oder falsch.

Zitat von N1570:

6.5.13 Logisches UND Operator

[...]

3 Der & & Luftfahrtunternehmer 1 ergeben, wenn beide Operanden ungleich 0 vergleichen ; ansonsten ergibt 0. Das Ergebnis hat den Typ int.

4 Im Gegensatz zum bitweisen binären Operator & garantiert der Operator & & eine Links-nach-Rechts-Auswertung; Wenn der zweite Operand ausgewertet wird, gibt es einen Sequenzpunkt zwischen den Auswertungen des ersten und zweiten Operanden. Wenn der erste Operand gleich 0 ist, wird der zweite Operand nicht ausgewertet.

6.5.14 Logical OR-Operator

[...]

3 Die || der Operator soll 1 ergeben, wenn einer seiner Operanden ungleich 0 vergleicht; ansonsten ergibt 0. Das Ergebnis hat den Typ int.

4 Im Gegensatz zur bitweisen | Betreiber, der || Betreiber garantiert Links-zu-Rechts-Bewertung; Wenn der zweite Operand ausgewertet wird, liegt ein Sequenzpunkt zwischen den Auswertungen der ersten und zweiten Operanden.Wenn der erste Operand ungleich 0 vergleicht, wird der zweite Operand nicht ausgewertet.

+0

Ah, ok ... das macht Sinn. Ich hatte den Eindruck, wenn LHS falsch wäre, würde es einen Kurzschluss geben, aber ich sehe das Gegenteil von &&. Danke für den Nebel! –

+0

Ich wusste, dass der zweite Teil wahr sein würde ... Ich dachte ursprünglich, der zweite Teil würde nicht ausgewertet werden, wenn der erste Teil falsch wäre (&& Verhalten). Mehr verwirrende C-Semantik in meinem Kopf zu speichern !! :) –

2

-Code, den Sie hatte:

((attr & 2) != 2) || ((attr & 4) != 4)) 

Was geschieht:

  1. (attr & 2) wertet bis 2 (0010 und 0010 = 0010, das 2)
  2. (2 != 2)-0 auswertet, oder falsch.
  3. Jetzt wird die rechte Seite des OR ausgewertet (Wenn die linke Seite wahr ist, dann würde die rechte Seite nicht ausgeführt/ausgewertet werden, dh "Kurzschluss". Aber in diesem Beispiel ist es falsch, also die rechte Seite ist bewertet).
  4. (attr & 4) ist die bitweise Operation, z. 0010 & 0100. Es ergibt sich zu 0000, oder 0.
  5. (0 != 4) wertet 1, oder wahr, so dass der Körper der If-Anweisung ausgeführt wird.
  6. Der Rest des Programms (die letzte Anweisung) wird dann ausgeführt und das Programm wird beendet.

Denken Sie daran:

  • & ist bitweise AND.
  • && ist Boolean UND.
  • | ist bitweises ODER.
  • || ist Boolean OR.
0

zwei Wege, ist können Sie das Kurzschlussverhalten in C erhalten:

unsigned int bitwise_logical_or(unsigned int p, unsigned int q) { 
    return (p | (q & ((p != 0) - 1))); 
} 

unsigned int numerical_logical_or(unsigned int p, unsigned int q) { 
    return p + (p == 0) * q; 
} 

Wie in anderen Antworten erwähnt, der || Operator gibt true (0x01) oder falsch (0x00).

bitwise_logical_or funktioniert wie folgt:

Wenn bit- oder auf ganze Zahlen p und q ausgeführt wird, wird es nur funktionieren, solange p Null ist. Wenn p nicht Null ist, bitweise oder wird p und q auf unvorhersehbare Weise vermischen. Wenn q auf Null gesetzt werden könnte, wenn p größer als Null ist, erhalten wir das gewünschte Ergebnis. Wenn p nicht Null ist, möchten wir daher bitweise und zwischen q und null durchführen. Der Trick ist, dass das einfache Testen von p == 0 (in 8 Bit) 0x00 oder 0x01 zurückgibt. Wir brauchen es, um 0xff oder 0x00 passend zurückzugeben. Wir erreichen dies, indem wir p! = 0 überprüfen, das wird 0x01 zurückgeben, wenn p> 0 und 0x00, wenn p == 0. Subtrahiere 1, und für den Fall, dass p> 0 ist, erhältst du 0x00 (falsch). Wenn p == 0 ist, haben Sie bereits 0x00 (alle Nullen), es gibt keinen Ort, an dem die Integer umgeht (Unterläufe) und Sie erhalten 0xff (alle Einsen).