Unterschied & und && Operator



  • Hallo,

    ich kann ja in c++ einfach boolische Ausdrücke mit dem && Operator verbinden und verknüpfen.
    Den & Operator kenn ich nur von Zeigern (Adresse eines Zeigers)

    Ich habe gerade ein Programm gefunden, in welchem zwei Statements mit einem einfachen & verknüpft waren. Komisch aber es funktioniert trotzdem ....
    Kann mir einer erklären warum??? und was ein einfaches & in diesen Zusammenhang bedeutet und ob es gar erlaubt ist .....
    Kurzes Programm dazu ... (dachte erst er überprüft nur die erste Bedingung ...)

    int start = 2;
    int a = 1;
    int b = 3;
    int c = 6;
    int ende = 5;

    if ((a > start)&(a < ende)) {cout << "(a > start)&(a < ende)" << endl;}
    if ((b > start)&(b < ende)) {cout << "(b > start)&(b < ende)" << endl;}
    if ((c > start)&(c < ende)) {cout << "(c > start)&(c < ende)" << endl;}
    /// oder
    if ((a > start)&&(a < ende)) {cout << "(a > start)&&(a < ende)" << endl;}
    if ((b > start)&&(b < ende)) {cout << "(b > start)&&(b < ende)" << endl;}
    if ((c > start)&&(c < ende)) {cout << "(c > start)&&(c < ende)" << endl;}

    ==> Ausgabe am Bildschirm...
    (b > start)&(b < ende)
    (b > start)&&(b < ende)

    Grüße
    balou



  • Dieser Thread wurde von Moderator/in akari aus dem Forum VCL (C++ Builder) in das Forum C++ verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • & -> binäres und
    Die Bits der zwei Werte werden verglichen - jedes Bit, das bei beiden Werten gesetzt ist, wird auch im Ergebnis gesetzt sein.

    && -> logisches und
    Ist der erste Ausdruck wahr (ungleich 0) und der zweite Ausdruck wahr (ungleich 0), so wird auch das Ergebnis wahr sein (1).

    Eine Abfrage ala "if (1 & 4)" wird wahr sein, wenn beide Werte mindestens ein gemeinsam gesetztes Bit haben. Denn in dem Fall wird das Ergebnis größer als 0 sein, und ist damit wahr.



  • Ah okay Danke!

    D.h. if (1 & ungeradeZahl) wird immer wahr sein .... bei ner geraden nicht ...

    Danke noch mal ...
    Grüße
    balou



  • balou123 schrieb:

    D.h. if (1 & ungeradeZahl) wird immer wahr sein .... bei ner geraden nicht ...

    Ja. Ist quasi die optimierte Version von "if (n % 2 == 1)" (Bitoperationen sind schneller als ne Division). Abre das optimiert der Compiler in der Regel sowieso.



  • Ich ignoriere jetzt mal überladene Operatoren.

    Bei "a & b" (binäres Und) ist das Ergebnis eine Ganzzahl, welche sich durch bitweises-Und der Operanden ergibt. Beide Seiten werden auf jeden Fall und in einer undefinierten Reihenfolge ausgewertet, um das Ergebnis zu berechnen. Beispiel: 6 & 3 --> 2, da

    binär dezimal
    00110    6
    00011    3
    ------------
    00010
    

    Bei "a && b" (logisches Und) ist das Ergebnis true oder false . Die Operanden werden durch && zu bool konvertiert, falls sie es nicht schon sind. Allerdings wird der zweite Operand nur dann ausgewertet, wenn der erste true liefert. Man bezeichnet es deswegen auch als "kurzschließendes" Und. Das erlaubt einem zB so etwas:

    if (zeiger && zeiger->dings==2) {
    }
    

    Wenn zeiger hier ein Nullzeiger ist, wird der zweite Teil schon nicht mehr ausgewertet. Es wird also garantiert nicht ein Nullzeiger dereferenziert.

    balou123 schrieb:

    Ich habe gerade ein Programm gefunden, in welchem zwei Statements mit einem einfachen & verknüpft waren. Komisch aber es funktioniert trotzdem ....
    Kann mir einer erklären warum???

    if ((a > start) &  (a < ende)) {cout << "(a > start)&(a < ende)" << endl;}
    /// oder
    if ((a > start) && (a < ende)) {cout << "(a > start)&&(a < ende)" << endl;}
    

    In beiden Fällen sind die Operanden vom Typ bool.

    Im ersten Fall werden beide Operanden ausgewertet, zu int konvertiert (integral promotion, also false-->0, true-->1), ein binäres Und angewendet und wieder zu bool für die if-Bedingung konvertiert (0-->false, sonst-->true)

    Im zweiten Fall wird zunächst nur der erste Operand ausgewertet. Falls da false bei rauskommt wird der zweite nicht mehr ausgewertet. Falls true rauskommt wird der zweite Operand ausgewertet und je nachdem, was da rauskommt, der Block ausgeführt oder nicht.

    kk



  • krümelkacker schrieb:

    Es wird also garantiert nicht ein Nullzeiger dereferenziert.

    Soweit ich weiss, kann man bei einigen Kompilern bei den Optionen einstellen, dass boolsche Ausdrücke immer komplett ausgewertet werden. Es ist also durchaus möglich, auf diese Weise einen Nullzeiger zu dereferenzieren.

    MfG, Jochen



  • Das ist dann aber kein C++ mehr.



  • Dteht das im C++ Standard, dass boolsche Ausdrücke nicht ganz ausgewertet werden müssen UND dass die Ausdrücke von links nach rechts abgearbeitet werden müssen? Ich persönlich würde mich nicht darauf verlassen.
    Da schreibe ich doch lieber sowas: if(pObj)pObj->DoSomething();
    Finde ich persönlich sicherer, lasse mich aber gerne belehren.


  • Mod

    Jochen S. schrieb:

    Dteht das im C++ Standard, dass boolsche Ausdrücke nicht ganz ausgewertet werden müssen UND dass die Ausdrücke von links nach rechts abgearbeitet werden müssen? Ich persönlich würde mich nicht darauf verlassen.
    Da schreibe ich doch lieber sowas: if(pObj)pObj->DoSomething();
    Finde ich persönlich sicherer, lasse mich aber gerne belehren.

    Doch das steht so drin. Genauso bei ||, wenn das erste schon true ist, wird beim zweiten gar nicht mehr geguckt. soll ich die Stelle raussuchen oder glaubst du mir das auch so? Das ist eine weit verbreitete Programmiertechnik, wie z.B. die besagte Verhinderung von Nullpointerdereferenzierung.



  • Jochen S. schrieb:

    Dteht das im C++ Standard, dass boolsche Ausdrücke nicht ganz ausgewertet werden müssen UND dass die Ausdrücke von links nach rechts abgearbeitet werden müssen? Ich persönlich würde mich nicht darauf verlassen.

    Doch, natürlich kann man sich auf die Short-Circuit-Evaluation-Semantik von && und || verlassen. Es steht im C++-Standard, dass bei

    true || a;
    false && b;
    

    weder a noch b ausgewertet werden dürfen.



  • Wäre schrecklich, wenn das nicht gehen würde, denn es gibt sehr viele:

    foo* pf = some_bar();
    
    if ( pf && pf->get_value() == 2 ) {...}
    


  • @SeppJ: Ich glaubs dir. Du musst das jetzt nicht extra wegen mir suchen.


Anmelden zum Antworten