interessantes phänomen



  • Das ist einfach undefiniertes Verhalten. Das ist vergleichbar mit:

    j = ++i + ++i;
    

    Das lernt man eigentlich in jedem C- oder C++-Grundkurs. Wann welcher Teilausdruck ausgewertet wird ist nicht definiert. Das hat nichts mit komischen Compilern zu tun, sondern ist einfach nicht definiert. Der Compiler kann sich entscheiden, zuerst die foo()-Aufrufe in welcher Reihenfolge auch immer auszuwerten und dann die operator<<-Aufrufe.



  • Dann wollen wir das mal aufdröseln:

    cout<<foo()/*1*/<<foo()/*2*/;
    
       =
    
    operator<<(
      opoperator<<(
        cout,
        foo()/*1*/
      ),
      foo()/*2*/
    );
    

    Es ist klar definiert, daß alle benötigten Teilausdrücke berechnet werden, bevor sie zusammenkommen - insbesondere wird der innere op<<-Aufruf und der zweite foo() ausgeführt, bevor der äußere op<< drankommen kann. Aber es ist nicht vorgeschrieben, in welcher Reihenfolge die Parameter einer Funktion berechnet werden, also steht es einem Compiler frei, erst den unteren foo()-Aufruf und danach den inneren op<< abzuarbeiten (oder auch umgekehrt) - im ersten Fall lautet das Ergebnis "10", im letzten Fall "01".
    (klarer Fall von undefniertem Verhalten)



  • Erläuternd dazu könnte man noch sagen - die Reihenfolge ist innerhalb einen Sequenzpunktes nicht definiert. Nach der Zeile cout << foo () << foo(); muss aber auf jeden Fall 10 oder 01 da stehen.



  • tntnet schrieb:

    Das ist einfach undefiniertes Verhalten.

    Unspezifiziert, nicht undefiniert. Jede mögliche Reihenfolge ist erlaubt, aber keine Nasendämonen.



  • C++-Standard; Kapitel 5 Expressions; Absatz 4

    Except where noted, the order of evaluation of operands of individual operators and subexpressions of individual
    expressions, and the order in which side effects take place, is unspecified.53) Between the previous
    and next sequence point a scalar object shall have its stored value modified at most once by the evaluation
    of an expression
    . Furthermore, the prior value shall be accessed only to determine the value to be stored.
    The requirements of this paragraph shall be met for each allowable ordering of the subexpressions of a full
    expression; otherwise the behavior is undefined.
    [Example:
    i = v[i++]; // the behavior is unspecified
    i = ++i + 1; // the behavior is unspecified
    —end example]

    Gruß
    Werner



  • Exceptional C++ schrieb:

    Schreiben Sie niemals Code, der von der Reihenfolge der Auswertung von Funktionsargumenten abhängt.



  • Werner Salomon schrieb:

    C++-Standard; Kapitel 5 Expressions; Absatz 4

    Except where noted, the order of evaluation of operands of individual operators and subexpressions of individual
    expressions, and the order in which side effects take place, is unspecified.53) Between the previous
    and next sequence point a scalar object shall have its stored value modified at most once by the evaluation
    of an expression
    . Furthermore, the prior value shall be accessed only to determine the value to be stored.
    The requirements of this paragraph shall be met for each allowable ordering of the subexpressions of a full
    expression; otherwise the behavior is undefined.
    [Example:
    i = v[i++]; // the behavior is unspecified
    i = ++i + 1; // the behavior is unspecified
    —end example]

    Gruß
    Werner

    Ohne zu erwähnen, dass ein Funktionsaufruf ein Sequenzpunkt ist, könnte man diesen Abschnitt missverstehen.


Anmelden zum Antworten