Anfänger: Boolsche Ausdrücke



  • Hey,
    ich fange grade an mich mit C++ zu beschäftigen und habe eine Frage bezüglich boolscher Ausdrücke. Angenommen ich habe drei ints a,b, und c. Kann mir jemand die Vorgehensweise erklären wie folgende Ausdrücke ausgewertet werden bzw. warum manche Variablen erhöht und andere wieder nicht erhöht werden.

    int a = 2, b = 2, c = 2;
    ++a && ++b || ++c
    
    int a = -2, b = -2, c = -2;
    ++a || ++b && ++c
    

    Freue mich über eine Antwort.
    Gruß rootrocker



  • versuch du es doch einmal
    so siehts irgendwie aus wie hausaufgaben und "keine lust, ich frag einfach nach"



  • Beim Schachspielen ists vielleicht noch cool, wenn man in einem Zug zwei Sachen abfertigt, aber beim Programmieren sollte mans lieber auf eine Anweisung pro Zeile belassen, sonst kriegt der nächste, der den Code liest ne Krise weil du zu viel gleichzeitig machen willst.
    Ansonsten google. https://de.m.wikibooks.org/wiki/C%2B%2B-Programmierung/_Einführung_in_C%2B%2B/_Verzweigungen#Logische_Operatoren



  • hmmm...danke erstmal. Wenns ne Hausaufgabe wäre, könnte ich mir ja eigentlich gleich das Ergebnis ausgeben lassen. Darum gehts mir aber nicht. Ich möchte verstehen wie das ausgewertet wird.
    Meine Gedanken dazu:

    int a = 2, b = 2, c = 2;
    ++a && ++b || ++c
    

    a wird auf 3 erhöht. Damit a AND b aber wahr ist, wird b auch erhöht. b ODER c sind so oder so wahr. Also kann c auch erhöht werden. Da passt es aber ja schonmal nicht.c bleibt 2.



  • Hastt du dir den Link überhaupt angeschaut? && wird wegen höherer Priorität zuerst ausgewertet und stellt EINEN boolschen Ausdruck dar. Von links nach rechts. also erst ++a, dann ++b. Und weil a und b ungleich 0 sind ist der Ausdruck wahr und die Auswertung wird abgebrochen, weil das || das Ergebnis nicht mehr verändern kann (ist jetzt so oder so true). Und benutz Klammern bei mehreren Auswertungen, ist übersichtlicher

    a && b || c ist gleich (a && b) || c
    


  • Naja, es geht darum, ob der Ausdruck wahr oder unwahr ist. Wenn ++a und ++b mit && verknüpft worden sind, steht das Ergebnis des gesamten Ausdrucks fest: Er ist wahr, egal was die Auswertung von ++c ergeben würde, weil ++a && ++b auf der einen Seite mit einer oder - Verknüpfung mit ++c auf der anderen Seite verknüpft ist.
    Da der Wert des Ausdrucks also schon feststeht, wenn die Anweisungen links von || ausgewertet sind, werden die Anweisungen rechts des || gar nicht mehr ausgeführt, denn sie sind nicht relevant. ++c wird also gar nicht ausgeführt -> c behält seinen Wert.
    Das Ergebnis ist nicht vorhersehbar, also undefiniert, denn genau so gut hätte der Compiler zuerst ++c auswerten können, hätte festgestellt, dass der Gesamtausdruck wahr ist, und dann die Anweisungen links von || ignorieren können.



  • edit: ich habs mal für ++a && (++b || ++c) beschrieben; huch 😃

    && ist linksassoziativ
    also:
    ++a && ...
    da a ungleich -1 ist, wird der ausdruck weiter ausgewertet.
    falls a (zuvor) -1 ist, ist es jetzt 0 und der ausdruck wird nicht weiter ausgewertet.

    || ist linksassoziativ
    also:
    ++b || ++c
    wenn b != -1 ist, ist b auch wahr und wir kommen noch zum letzten teil. wenn b == -1, wird hier abgebrochen.

    also:

    a    |   b   |   c   |    E
    ---------------------------------
      -1   |   .   |   .   |  falsch; ++a
     != -1 | != -1 |   .   |  richtig; ++a, ++b
     != -1 |   -1  |   .   |  (c != -1); ++a, ++b, ++c
    

    usw.



  • Belli schrieb:

    Das Ergebnis ist nicht vorhersehbar, also undefiniert, denn genau so gut hätte der Compiler zuerst ++c auswerten können, hätte festgestellt, dass der Gesamtausdruck wahr ist, und dann die Anweisungen links von || ignorieren können.

    Nee, das stimmt (zum glück) nicht. Im Gegensatz zur Auswertung von Funktionsparametern, ist hier die Reihenfolge festgelegt.



  • Belli schrieb:

    Das Ergebnis ist nicht vorhersehbar, also undefiniert, denn genau so gut hätte der Compiler zuerst ++c auswerten können, hätte festgestellt, dass der Gesamtausdruck wahr ist, und dann die Anweisungen links von || ignorieren können.

    Durch die Postinkrements wird kein Wert auf 0 gesetzt, also sind die quasi egal.
    Und bei beiden Ausdrücken kommt 1 raus, wenn mindestens 2 Variablen != 0 sind. 🙂


  • Mod

    unskilled schrieb:

    && ist linksassoziativ

    Das ist zwar richtig aber hier irrelevant. Assoziativität beschreibt, in welcher Weise bei Verkettung mehrerer Operatoren gleichen Ranges Subausdrücke zu Operanden zusammengefasst werden. Über die Auswertungsreihenfolge sagt das nur insoweit etwas aus, als nat. Subausdrücke zuerst ausgewertet werden müssen, bevor deren Ergebnis als Operand weiterverwendet werden kann. Es hat jedenfalls nichts damit zu tun, dass der eingebaute &&-Operator stets zunächst den linken Operanden auswertet bevor ggf. auch der rechte ausgewertet wird.
    Im Standard werden die Präzedenz und Assoziativität nicht direkt so benannt, diese ergeben sich implizit durch die Grammatik, z.B.:

    logical-and-expression:
        inclusive-or-expression
        logical-and-expression && inclusive-or-expression
    

    Die EBNF-Form ist linksrekursiv, das entspricht der Linksassoziativität des Operators.

    Vgl. rechtsassoziative Zuweisungsoperatoren:

    assignment-expression:
        conditional-expression
        logical-or-expression assignment-operator assignment-expression
        throw-expression
    

    (C++03 Grammatik). Die Rekursion für assignment-expression findet hier rechts vom Operator statt.


Anmelden zum Antworten