Grundlagen: i++ & ++i

Was ist eigentlich der Unterschied zwischen i++ und ++i? So gesehen gehört das ja zum Grundwissen eines Programmierers. Ich bin mir jedoch recht sicher, dass zumindest der ein oder andere es bis vor Kurzem noch nicht wusste ;)

Informatik Anfänger müssen sich zumindest nicht dafür schämen die Antwort gegooglet zu haben. Die folgenden Beispiele sind in C# geschieben, gelten jedoch im Prinzip auch für Java.

Sowohl ++i als auch i++ inkrementieren i um 1. Der Unterschied ist das “Ergebnis” dieser Auswertung. Damit meine ich nicht das Ergebnis, dass i um eins größer geworden ist, sondern den Rückgabewert. Man könnte ja auf die Idee kommen x = ++i zu schreiben und y = i++. In diesem Fall wären x und y nicht gleich. ++i inkrementiert zuerst i und wird dann zugewiesen, i++ wird zuerst zugewiesen und dann inkrementiert. Die Variable x wäre in diesem Beispiel also um eins größer als y.

Als Funktion kann man sich das in etwa so vorstellen für i++

static int VarPlusPlus(ref int variable) { int tmp = variable; variable += 1; return tmp; }

und wie folgt für ++i.

static int PlusPlusVar(ref int variable) { variable += 1; return variable; }

Das ref bedeutet übrigens, dass i als Referenz übergeben wird und Änderungen in der Funktion an i auch außerhalb gültig sein werden (so wie man es von Objekten gewohnt ist). Aber das zu erklären ist ein anderes Thema.

Falls der Unterschied weiterhin nicht klar sein sollte, kann man es sich an einem kleinen Test verbildlichen. Unser Code:

Console.WriteLine("i++"); int i = 0; Console.WriteLine("A: " + i++); Console.WriteLine("B: " + i); Console.WriteLine("++i"); i = 0; Console.WriteLine("A: " + ++i); Console.WriteLine("B: " + i);

und für die beiden Funktionen von oben

Console.WriteLine("VarPlusPlus"); i = 0; Console.WriteLine("A: " + VarPlusPlus(ref i)); Console.WriteLine("B: " + i); Console.WriteLine("PlusPlusVar"); i = 0; Console.WriteLine("A: " + PlusPlusVar(ref i)); Console.WriteLine("B: " + i);

Und wie wirkt sich das auf Schleifen aus? Die kurze Antwort lautet: in C# kein bischen. Die lange Antwort braucht etwas mehr Platz. Zuerst der einfache Teil. Das Ergebnis der beiden folgenden Schleifen ist gleich, da der dritte Block der for-Schleife separat ausgewertet wird und die inkrementierte Variable verwendet wird, nicht der oben erwähnte Rückgabewert (es könnte dort ja auch x += 4 stehen).

Console.Write("i++ loop"); for (i = 0; i < 5; i++) { Console.Write(" " + i); } Console.WriteLine(); Console.Write("++i loop"); for (i = 0; i < 5; ++i) { Console.Write(" " + i); }

Man wird trotzdem häufiger über Menschen stolpern, die ++i in for-Schleifen bevorzugen. Die Gründe hierfür sind verschieden, es fängt mit der persönlichen Preferenz an und endet mit Performance-Argumenten. So wird es hier und da heißen, dass i++ über ++i implementiert wird und i++ intern eine Kopie benötigt (vergleichbar mit den beiden oben erwähnten Funktionen).

Betrachtet man C# so ist dies allerdings keine wahre Aussage, zumindest nachdem der C# Compiler drübergelaufen ist. Denn das Resultat ist in C# völlig identisch und ich würde behaupten, dass dies auch für die meisten anderen Hochsprachen gelten wird.

Woher kommt dieser “Mythos” also? Lässt man den Personenkreis der einfach “anders” sein möchte mal außen vor, so werden es meistens ehemalige C++ Programmierer sein die (beim Namen C++ ausgerechnet) ++i bevorzugen. Denn gerade dort gehört es zum guten Ton die Präfix-Schreibweise zu verwenden. Ohne es zu wissen, würde ich zwar kurzerhand behaupten, dass die zusätzliche Kopie bei einem Integer auch bei C++ vom Compiler “wegoptimiert” wird, jedoch muss man ein wichtiges Detail beachten. C++ unterstüzt das Überschreiben von Operatoren und im Vergleich zu C# kann dort eben auch das ++ überschrieben werden. Und dafür, dass diese zusätzliche Kopie auch bei komplexen Klassen und in allen Fällen wegoptimiert wird, würde ich meine Hand nicht ins Feuer legen. Erst recht nicht wenn es um die Compiler vor 10, 20 oder mehr Jahren geht.

Lasst euch in C# oder Java also nicht von i++ oder ++i in for-Schleifen verwirren, da passiert nichts magisches. Der Programmierer hat sich einfach über Jahre an die Prefix-Schreibweise gewöhnt, oder möchte einfach ein wenig besonders sein :)

Paul Rupek ● 20:57:20 11.04.2011 ● Alles anzeigen ● Abgelegt in: Code


Kommentare

He Paul,

ein guter Blog! Inhalt, Design und Aufmachung gefällt mir.

Das es in C# egal ist ob man i++ oder ++i schreibt liegt an der Umsetzung in IL-Code, die erfolgt (glaube ich) gleich. In C ist ++i wirklich schneller. Demnach kann ich nur bestätigen was du da schreibst :)

Gruß
Patrick

#2161, geschrieben von Patrick Koglin 25.01.2012 @ 20:30:08

Hi & vielen Dank :)
Ist mangels Beiträgen leider ein wenig eingerostet, du wirkst da ein ganzes Stückchen aktiver ;)

#2356, geschrieben von Paul Rupek 20.02.2012 @ 23:16:16