Vorrang und Verständnis



  • Hallo,
    ich lerne C und bin neu im Forum.
    Im Moment steh ich aufm Schlauch.

    a = b = c = 0;
    erg = ++a || ++b && ++c;
    printf("erg = %d, a = %d, ", erg, a);
    printf("b = %d, c = %d", b, c);
    

    Das Programm spuckt folgendes aus:
    erg = 1
    a = 1
    b = 0
    c = 0

    Also, ich hab den Vorrang anscheinend falsch verstanden und fasse das mal mit Klammern zusammen:
    erg = (++a) || ((++b) && (++c));
    Zunächst die Inkrementation aller Variablen, dann das logische UND, dann erst das log. ODER.
    Das ++ steht links der Variable, also wird sofort inkrementiert.

    WIESO spuckt das Programm dann 0 aus für b und c? 😕

    Bitte helfen 😞



  • Weil || und && die Auswertung nach dem linken Operanden abbrechen, wenn dadurch das Ergebnis schon feststeht. Es wird also nur ++a ausgewertet, das ist 1, also wird der ||-Ausdruck auf jeden Fall wahr. ++b und ++c werden jetzt gar nicht erst ausgewertet.



  • Aber es ist schon richtig, dass das && Priorität hat?!
    Also wird zuerst der gesamte Operand links von && bearbeitet...
    und da es wieder eine log. Verkn. ist, wird wieder der linke Operand bearbeitet.
    Und dieser linke Operand ist wahr, demnach wird der Rest vernachlässigt...

    Ou man, jetzt hats *klick* gemacht.

    Ich danke dir!! 😃



  • einsdurchnull schrieb:

    Aber es ist schon richtig, dass das && Priorität hat?!

    Ja.
    🙂



  • Bei solchen Ausdrücken musst du höllisch vorsichtig sein!
    Gerade wegen der logischen Operatoren werden die Inkrement- und Dekrement-Operatoren nicht immer ausgeführt. Auch ist die Reihenfolge der Auswertung - sofern durch Prioritäten nicht geändert - nicht definiert!

    --a || --b

    Es ist nicht definiert ob --a oder --b zuerst ausgewertet wird, jedoch können beide Auswertungen dazu führen, dass der jeweils andere Ausdruck nicht mehr ausgewertet wird.



  • Janjan schrieb:

    --a || --b

    Es ist nicht definiert ob --a oder --b zuerst ausgewertet wird, jedoch können beide Auswertungen dazu führen, dass der jeweils andere Ausdruck nicht mehr ausgewertet wird.

    Das glaube ich nicht.



  • Janjan schrieb:

    Auch ist die Reihenfolge der Auswertung - sofern durch Prioritäten nicht geändert - nicht definiert!

    Erstens hat die Operatorpriorität mit der Auswertungsreihenfolge der Operanden nicht viel zu tun, und zweitens gibt es ein paar Operatoren, bei denen die Auswertungsreihenfolge durchaus festgelegt ist. Soweit ich weiß, handelt es sich dabei um logisches Und, logisches Oder, Komma-Operator und Conditional Operator.

    Janjan schrieb:

    Es ist nicht definiert ob --a oder --b zuerst ausgewertet wird, jedoch können beide Auswertungen dazu führen, dass der jeweils andere Ausdruck nicht mehr ausgewertet wird.

    Das ist Unfug. Der Ausdruck ist wohldefiniert. Zuerst wird --a ausgewertet. Wenn das false ergibt (z.B. weil a ein int mit dem Wert 1 ist), wird --b ausgewertet.



  • Hi,

    die C FAQ schreibt, dass die Operatoren || und && eine Ausnahme in der Operatorhierarchie sind.

    http://www.dclc-faq.de/kap4.htm#4.5

    Das bedeutet, dass der Ausdruck

    erg = ++a || ++b && ++c
    

    von links nach rechts bearbeitet wird; völlig egal ob der ++ Operator Vorrang hat.

    Hat da vllt jemand ne Quelle, wo das genauer beschrieben wird?



  • einsdurchnull schrieb:

    Das bedeutet, dass der Ausdruck

    erg = ++a || ++b && ++c
    

    von links nach rechts bearbeitet wird; völlig egal ob der ++ Operator Vorrang hat.

    Mit dem Operatorvorrang hat das nichts zu tun. Die Vorrangregeln sind dafür da, bei Mehrdeutigkeiten zu entscheiden, was zusammengehört, beispielsweise ob ++a || ++b als ++(a|| (++b)) oder als (++a) || (++b) verstanden werden soll.



  • Du solltest besser alle neuen Zuweisungen auf a, b, c einzeln vornehmen und die boolschen Operatoren (und / oder) allein auf Abfragen verwenden. Das erhöht dein Verständnis. Die Vorrangstellung bei boolschen Operatoren ist klar geregelt von links nach rechts. Trifft eine Abfrage bereits zu, werden die nachfolgenden nicht mehr ausgewertet. Deine Codezeile erg = .... beinhaltet bereits eine solche Abfrage.
    Fange als Neuling in C ganz unten an mit einfachen überschaubaren Dingen. Aber auch später solltest du gewünschte Zuweisungen nicht in Abfragen verstecken.


Anmelden zum Antworten