poweroff Neuigkeiten

i++ vs. ++i

Sonntag, 23. Juli 2006 um 17:07 Uhr Christian

Nach einer interessanten Diskussion im IRC stellte sich mir heute die Frage:

$i = 1;
$i += ++$i + $i++;
print $i;

Was ist i?

Ergebnis:

Es hängt von der Implementierung ab.

C++: 7
PHP: 7
Perl: 8
Java: 5

Meine spontane Antwort war 5… ich dachte ich würde in C++ denken… aber vielleicht doch eher in Java ;)

Artikel gespeichert unter: OpenSource / Linux,Studium / Uni

bisher 10 Kommentare Eigenen Kommentar schreiben

  • 1. Gravatar blub  |  25.Juli 2006 um 10:30

    hmm, wie kommt perl auf die 8? 5 und 7 ist ja nachvollziehbar…

  • 2. Gravatar Sebastian Marsching  |  25.Juli 2006 um 19:45

    Ich habe an 7 gedacht, wobei ich davon ausgegangen wäre, dass das bei Java auch gilt.
    Auf die 7 bin ich gekommen, weil ich meine irgendwo gehört zu haben, dass die Ausdrücke von rechts nach links ausgewertet werden. “$i++” gibt somit 1 zurück, anschließend “++$i” gibt 3 zurück, die Summe aus beiden ist 4 und wird zu 3 addiert.

    Um zu sehen, wie man auf 5 bei Java kommt, muss man den erzeugten Bytecode anschauen:
    1. Variable wird mit dem Wert 1 initialisiert
    2. Variable wird auf Stack geladen
    3. Variable wird um 1 erhöht
    4. Variable wird zweimal auf Stack geladen
    5. Variable wird um 1 erhöht
    6. Die beiden obersten Stack-Elemente werden addiert, vom Stack entfernt und das Ergebnis wieder auf den Stack gelegt (2 + 2 = 4)
    7. Die beiden obersten Stack-Elemente werden addiert, vom Stack entfernt und das Ergebnis wieder auf den Stack gelegt (4 + 1 = 5)
    8. Das Ergebnis vom Stack wird in der Variablen gespeichert (damit ist der Wert 5).

    Das ist wohl so zu verstehen, das “+=” zunächst den vorhandenen Wert auf den Stack legt und anschließend die Operationen auf der rechten Seite durchführt. Der “+” Operator funktioniert dann wohl einfach so, dass zunächst der Teil links des Operators und dann der rechts des Operators ausgewertet und anschließend das Ergebnis addiert wird.

    Das Ergebnis von Perl lässt sich eigentlich nur so erklären, dass Perl immer den erhöhten Wert zum Weiterrechnen benutzt, unabhängig davon auf welcher Seite das “++” steht. Das würde dann nämlich (2 + 3) + 3 = 8 ergeben.

  • 3. Gravatar Christian  |  25.Juli 2006 um 22:19

    Besser als Sebastian hätte ich das auch nicht erklären können…. naja ehrlich gesagt nur schlechter ;)

  • 4. Gravatar Peter Eimers  |  30.Juli 2006 um 01:13

    Hallo,

    also post /- pre-increment ist doch relativ leicht erklärt:

    int i=0;
    System.out.println(i++);

    Ausgabe: 0

    /—————

    Gruß

    int i=0;
    System.out.println(++i);

    Ausgabe: 1

  • 5. Gravatar Christian  |  30.Juli 2006 um 18:20

    Das ist klar.
    Aber das die Auswertungsstrategie bei C++, Java und Perl unterschiedlich ist, ist nicht so offensichtlich.

  • 6. Gravatar MartinM  |  20.August 2006 um 22:42

    Gute Frage,

    ich bin wohl auch ein Java-Denker ;)
    Die anderen Ergebnisse kann ich nicht nachvollziehen.

    Aber genau solchen Garbage-Code wird niemand ernsthaft produzieren, weil das Verhalten nicht genau defniert ist.

  • 7. Gravatar indeterminatus  |  10.Oktober 2006 um 14:48

    Achtung, folgendes ist i-Tüpfelchen-Reiterei, nachdem es hier aber anscheinend um genau diese Feinheiten geht, dachte ich, ist es OK meinen Senf dazuzugeben.

    Die Antwort “C++: 7″ ist an sich schon ungenau, da C++ != C++. Zu welchem Zeitpunkt alle sogenannten side-effects aufgelöst werden, ist im C++ Standard (ISO IEC 14882:1998) nicht definiert. Der Grund dafür liegt in der Vergangenheit. Man hat versucht, Compilerbauern mehr Freiheiten bzgl. der Optimierung zu lassen, was durch eine strenge Regelung der Auswertungsreihenfolge zunichte gemacht würde. Es kann also durchaus sein, dass gcc 7 zurückliefert, MSVC hingegen 5, und trotzdem beide Compiler Standard-konform sind (ich sag jetzt damit nicht, DASS sie es wirklich sind :P ).

    Die Konsequenz daraus ist: Niemals Code schreiben, der Nebeneffekte ausnutzt. Der Programmierer, der obiges Beispiel im “echten” Code verewigt (und nicht etwa als Spielerei), gehört sofort gefeuert und getreten ;)
    Das gilt übrigens auch für alle Sprachen, in denen das Ergebnis klar definiert ist – die Lesbarkeit eines solchen Konstruktes lässt doch sehr zu wünschen übrig.

    Verfolge diesen Blob nicht, deswegen Kommentare bitte auch an mich per Mail :)

  • 8. Gravatar Tobias  |  17.Januar 2007 um 06:36

    @Sebastian
    Perl honoriert schon ob ++i oder i++. Man teste dies einfach mal mit:


    $i = 1;
    $i += $i++ + ++$i;
    print $i;

    und sollte als Ergebnis 7 erhalten.

    Interessant wird es auch, wenn man mal folgendes macht:


    # in perl
    $i = 0; @post = ($i++, $i++, $i++, $i++, $i++);
    $i = 0; @pre = (++$i, ++$i, ++$i, ++$i, ++$i);


    // in c / c++ / java
    int i;
    i = 0;
    int pre[] = { ++i, ++i, ++i, ++i, ++i };
    i = 0;
    int post[] = { i++, i++, i++, i++, i++ };

    Als Ergebnisse erhalte ich dabei …

    … in Java / Javascript und PHP:
    pre: 1 2 3 4 5
    post: 0 1 2 3 4

    … in C:
    pre: 1 2 3 4 5
    post: 0 0 0 0 0

    … in Perl:
    pre: 5 5 5 5 5
    post: 0 1 2 3 4

    Soviel zum Thema side effects ;)

  • 9. Gravatar ccr  |  22.März 2007 um 08:22

    Sorry, aber in C und C++ ist das Ergebnis undefiniertes Verhalten, der code, wie er da steht, ist schlichtweg illegal.

    http://c-faq.com/expr/evalorder2.html

  • 10. Gravatar Tomtom1  |  11.Oktober 2007 um 17:37

    @ccr : Hallo auch! Schön, dass du da bist. Keine Internetdiskussion ist vollständig, wenn kein Troll dabei war ;-)

    Es kann also nicht sein, was nicht sein darf. Das ist gut zu wissen

    Ich frag mich, was mit leuten passiert, die doch mal sowas doch mal schreiben. Schließlich ist es “schlichtweg illegal”. Holt die die Polizei ab? Was ist das Strafmaß? Gefängnis? Bußgeld?

    Also echt. Falsch ist beim Programmieren nur, was nicht den angestrebten Effekt erziehlt (inhaltlicher bug) oder eine Fehlermeldung produziert. Das macht es noch lange nicht illegal. Oder gibt’s für C und C++ neuerdings nen Gesetzgeber und Leute, die die Gesetze durchsetzen?

    Natürlich ist der Beispiel-Code Blödsinn. Er demonstriert schlicht, dass es in jedem ausreichend komplexen System Grenzfälle gibt, die nicht eindeutig definiert sind. Und deshalb macht es Sinn, sie zu vermeiden. Wenn ich aber nen Programm schreibe, dass auf ner klar definierten hardware und OS-software aufsetzen wird, dann können zeilen wie aus dem beispiel sinn machen. versuch mal, das BIOS von nem Handy so klein zu machen, dass es in den chip passt, oder nen programm zu schreiben, das nen fertigungsroboter steuert

    in deinem verlinkten text steht übrigens nix von illegal. da steht “undefined behavior” und dass es eine schlechte idee ist, solchen code zu schreiben

Ihr Kommentar

Pflichtfeld

Pflichtfeld, anonym

Folgende HTML-Tags sind erlaubt:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">

Trackback  |  PDF


Kalender

Juli 2006
M D M D F S S
« Jun   Okt »
 12
3456789
10111213141516
17181920212223
24252627282930
31  

Aktuelle Artikel