dekrementieren



  • unskilled schrieb:

    die sollte aber hier relativ egal sein...

    Sollte sie? Was, wenn der Compiler zuerst alle ++ auswertet und dann addiert? Das ist nicht verboten.



  • Ich komme auf 30.

    VC++ 6 liefert aber auch 31.



  • Nexus schrieb:

    unskilled schrieb:

    die sollte aber hier relativ egal sein...

    Sollte sie? Was, wenn der Compiler zuerst alle ++ auswertet und dann addiert? Das ist nicht verboten.

    Und wäre das nicht auch egal?



  • Roger Wilco schrieb:

    Und wäre das nicht auch egal?

    Natürlich nicht. Wenn er zuerst alle Teilausdrücke inkrementiert, kommt wohl eine andere Summe zustande, als wenn er sie zum Beispiel nach jeder einzelnen Addition wieder inkrementiert.

    Tatsache ist, auf eine Variable darf zwischen zwei Sequenzpunkten (dazu gehören zum Beispiel die Operatoren &&, || und ,) nicht mehrfach zugegriffen werden, wenn sie in dieser Zeit verändert wird.



  • Ach so, du meinst:

    std::cout << 4 + 4 + 4 + 4 + 4 << std::endl;
    

    Edit: Nee, meinst Du nicht^^



  • Nexus schrieb:

    unskilled schrieb:

    die sollte aber hier relativ egal sein...

    Sollte sie? Was, wenn der Compiler zuerst alle ++ auswertet und dann addiert? Das ist nicht verboten.

    Oo Hab ich noch nicht gewusst... Dachte bisher immer - da der Preinc-op das Rückgeben impliziert, dass das auch (direkt) nacheinander ausgeführt wird...
    aber ok - mein fehler ^^

    bb



  • Bei mir kommt bei

    int i = 3;
    std::cout << (++i) + (++i) << std::endl;
    

    zum Beispiel 10 raus, was mich darauf schliessen lässt, dass er zuerst alle Inkremente durchführt und dann addiert. Genauso erlaubt wäre es, zuerst einen Summanden zu inkrementieren (-> 4) und dann diesen zu dem zweiten inkrementierten (-> 5) zu addieren, was folglich zu einem anderen Resultat führt.



  • int wert=3;
    int res =  ++wert + ++wert + ++wert + ++wert + ++wert ; //31
    

    VS 2008 sagt 40.



  • Nexus schrieb:

    Bei mir kommt bei

    int i = 3;
    std::cout << (++i) + (++i) << std::endl;
    

    zum Beispiel 10 raus, was mich darauf schliessen lässt, dass er zuerst alle Inkremente durchführt und dann addiert. Genauso erlaubt wäre es, zuerst einen Summanden zu inkrementieren (-> 4) und dann diesen zu dem zweiten inkrementierten (-> 5) zu addieren, was folglich zu einem anderen Resultat führt.

    ja, so sah es bei mir auch aus, aber wenn du dann ein weiteres ++i anhängst, kommt bei mir 16 (statt der erwarteten 15) heraus.



  • unskilled schrieb:

    Oo Hab ich noch nicht gewusst... Dachte bisher immer - da der Preinc-op das Rückgeben impliziert, dass das auch (direkt) nacheinander ausgeführt wird...
    aber ok - mein fehler ^^

    Über Auswertungsreihenfolgen sollte man nicht zu fest spekulieren, geschweige denn Code davon abhängig machen. Das Problem gibt es nicht nur bei arithmetischen Ausdrücken, sondern zum Beispiel auch bei Funktionsaufrufen. Das ist auch ein Grund für gewisse merkwürdig erscheinende Schnittstellen bei Boost, weil Exceptionsicherheit unabhängig von der Parameter-Auswertungsreihenfolge garantiert werden soll.

    NEWc++MAN schrieb:

    ja, so sah es bei mir auch aus, aber wenn du dann ein weiteres ++i anhängst, kommt bei mir 16 (statt der erwarteten 15) heraus.

    Nochmals: Da gibt es nichts zu erwarten, das Verhalten ist schlicht und einfach undefiniert!



  • Hallo,
    wie knivil schon richtig bemerkte ist das Verhalten undefiniert und deshalb ist
    es müßig darüber zu reden was bei wem rauskommt. Jede Reaktion ist aus Sicht
    des Standards ok.

    Eines meiner Lieblingszitate aus dem C++ Standard:

    Between the previous and next sequence point an 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

    Und natürlich gibt's da auch was von Wikipedia:
    http://en.wikipedia.org/wiki/Sequence_point



  • Nexus schrieb:

    Nochmals: Da gibt es nichts zu erwarten, das Verhalten ist schlicht und einfach undefiniert!

    Naja, undefiniert wohl nicht, aber schwer voraus zusagen. Denn nach irgendwelchen Regeln wird das schon ausgewertet, aber die Möglichkeiten sind wohl zahlreich.

    Aber so undefiniert wie ein Zugriff auf Speicherstelle xyz wird es nicht sein. Ein Ergebnis von -56439 z.B. wird es nie geben. Auf ein und dem selben Compiler bei den selben Einstellungen wird das Ergebnis immer gleich bleiben.

    (Vermute ich^^ ;))



  • Roger Wilco schrieb:

    Nexus schrieb:

    Nochmals: Da gibt es nichts zu erwarten, das Verhalten ist schlicht und einfach undefiniert!

    Naja, undefiniert wohl nicht, aber schwer voraus zusagen. Denn nach irgendwelchen Regeln wird das schon ausgewertet, aber die Möglichkeiten sind wohl zahlreich.

    Aber so undefiniert wie ein Zugriff auf Speicherstelle xyz wird es nicht sein. Ein Ergebnis von -56439 z.B. wird es nie geben. Auf ein und dem selben Compiler bei den selben Einstellungen wird das Ergebnis immer gleich bleiben.

    (Vermute ich^^ ;))

    Nein, es ist undefiniert. Vor allem, da mit mit einem Ergebnis nachfolgend noch irgendwie weiterarbeitet (z.B. ein Array indiziert)...

    Ich zitiere nochmal den Standard:

    SO/IEC 14882:2003 schrieb:

    Except where noted, the order of evaluation of operands of individual operators and subexpressions of indi-
    vidual 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.



  • Roger Wilco schrieb:

    Naja, undefiniert wohl nicht, aber schwer voraus zusagen.

    Nach dem Standard ist das Verhalten "unspecified", was so viel bedeutet wie compiler-abhängig, aber der Compiler braucht es nicht zu dokumentieren. Da man sich auf rein keine Regeln verlassen kann, ist das Verhalten so gut wie undefiniert.

    Übrigens ist es auch nicht Zufall, was im Speicher steht. Es hängt vielleicht von etwas mehr Faktoren ab, aber theoretisch wäre es auch deterministisch.



  • Der Standard ist Müll


Anmelden zum Antworten