Was ist in C der Unterschied zwischen der Verwendung von ++i
und i++
und welche sollte im Inkrementierungsblock einer for
Schleife verwendet werden?
c
for-loop
post-increment
pre-increment
The.Anti.9
quelle
quelle
Antworten:
++i
erhöht den Wert voni
und gibt dann den inkrementierten Wert zurück.i++
erhöht den Wert voni
, gibt jedoch den ursprünglichen Wert zurück,i
der vor dem Inkrementieren gehalten wurde.Für eine
for
Schleife funktioniert beides.++i
scheint häufiger zu sein, vielleicht weil dies in K & R verwendet wird .Befolgen Sie auf jeden Fall die Richtlinie "lieber
++i
alsi++
" und Sie werden nichts falsch machen.Es gibt ein paar Kommentare zur Effizienz von
++i
undi++
. In jedem Nicht-Studenten-Projekt-Compiler gibt es keinen Leistungsunterschied. Sie können dies überprüfen, indem Sie sich den generierten Code ansehen, der identisch ist.Die Effizienzfrage ist interessant ... hier ist mein Versuch, eine Antwort zu finden: Gibt es einen Leistungsunterschied zwischen i ++ und ++ i in C?
Wie @OnFreund feststellt, ist dies für ein C ++ - Objekt anders, da
operator++()
es sich um eine Funktion handelt und der Compiler nicht wissen kann, wie die Erstellung eines temporären Objekts für den Zwischenwert optimiert werden kann.quelle
for(int i=0; i<10; i++){ print i; }
Wird dies zum Beispiel nicht anders sein alsfor(int i=0; i<10; ++i){ print i; }
Mein Verständnis ist, dass einige Sprachen je nach Verwendung unterschiedliche Ergebnisse liefern.i++
weil er die Form "Operandenoperator" hat, a la eine Zuweisung "Operandenoperatorwert". Mit anderen Worten, der Zieloperand befindet sich auf der linken Seite des Ausdrucks, genau wie in einer Zuweisungsanweisung.i++
undprint i
in verschiedenen Anweisungen sind, sondern weili++;
undi<10
sind. @ jonnyflashs Bemerkung ist nicht so falsch. Angenommen, Sie habenfor(int i=0; i++<10){ print i; }
undfor(int i=0; ++i<10){ print i; }
. Diese funktionieren anders als @johnnyflash im ersten Kommentar beschrieben.i ++ ist bekannt als Beitrag Erhöhungsschritte während ++ i genannt wird Pre - Schritte.
i++
i++
ist nach dem Inkrementieren, da deri
Wert nach Abschluss der Operation um 1 erhöht wird.Sehen wir uns das folgende Beispiel an:
Hier Wert von
j = 1
aberi = 2
. Hier wird zuerst der Wert voni
zugewiesen undj
danni
erhöht.++i
++i
ist vor dem Inkrementieren, da deri
Wert vor der Operation um 1 erhöht wird . Es bedeutet,j = i;
wird nach ausgeführti++
.Sehen wir uns das folgende Beispiel an:
Hier Wert von
j = 2
aberi = 2
. Hieri
wirdj
nach demi
Inkrementieren von der Wert von zugewieseni
. Ebenso++i
wird vorher ausgeführtj=i;
.Für Ihre Frage, welche im Inkrementierungsblock einer for-Schleife verwendet werden soll? Die Antwort ist, Sie können jeden verwenden .. spielt keine Rolle. Es wird Ihre for-Schleife gleich Nr. Ausführen. von Zeiten.
Und
Beide Schleifen erzeugen die gleiche Ausgabe. dh
0 1 2 3 4
.Es ist nur wichtig, wo Sie es verwenden.
In diesem Fall wird ausgegeben
1 2 3 4 5
.quelle
Bitte machen Sie sich keine Sorgen über die "Effizienz" (Geschwindigkeit, wirklich), von der eine schneller ist. Wir haben heutzutage Compiler, die sich um diese Dinge kümmern. Verwenden Sie, was auch immer sinnvoll ist, basierend darauf, was Ihre Absicht klarer zeigt.
quelle
operator++(int)
Version (der Postfix-Version) muss der Code so ziemlich eine temporäre Version erstellen, die zurückgegeben wird. Sind Sie sicher, dass Compiler dies jederzeit optimieren können?++i
erhöht den Wert und gibt ihn dann zurück.i++
Gibt den Wert zurück und erhöht ihn dann.Es ist ein subtiler Unterschied.
Verwenden
++i
Sie für eine for-Schleife, da diese etwas schneller ist.i++
erstellt eine zusätzliche Kopie, die einfach weggeworfen wird.quelle
i++
: In diesem Szenario wird zuerst der Wert zugewiesen und dann erfolgt die Inkrementierung.++i
: In diesem Szenario wird zuerst das Inkrement durchgeführt und dann der Wert zugewiesenUnten ist die Bildvisualisierung und hier ist ein schönes praktisches Video , das dasselbe demonstriert.
quelle
Der Grund
++i
kann etwas schneller sein als deri++
,i++
dass eine lokale Kopie des Werts von i erforderlich sein kann, bevor er inkrementiert wird, während dies++i
niemals der Fall ist. In einigen Fällen optimieren einige Compiler es, wenn möglich ... aber es ist nicht immer möglich, und nicht alle Compiler tun dies.Ich versuche, mich nicht zu sehr auf Compiler-Optimierungen zu verlassen, daher folge ich dem Rat von Ryan Fox: Wenn ich beide verwenden kann, verwende ich
++i
.quelle
i
als des Werts 1, wenn Sie eine Anweisung schreiben1;
.Das effektive Ergebnis der Verwendung von entweder in einer Schleife ist identisch. Mit anderen Worten, die Schleife macht in beiden Fällen genau dasselbe.
In Bezug auf die Effizienz kann die Auswahl von i ++ gegenüber ++ i mit einer Strafe verbunden sein. In Bezug auf die Sprachspezifikation sollte die Verwendung des Post-Inkrement-Operators eine zusätzliche Kopie des Werts erstellen, auf den der Operator einwirkt. Dies könnte eine Quelle für zusätzliche Operationen sein.
Sie sollten jedoch zwei Hauptprobleme mit der vorhergehenden Logik berücksichtigen.
Moderne Compiler sind großartig. Alle guten Compiler sind intelligent genug, um zu erkennen, dass in einer for-Schleife ein ganzzahliges Inkrement angezeigt wird, und beide Methoden werden auf denselben effizienten Code optimiert. Wenn die Verwendung von Post-Inkrement gegenüber Pre-Inkrement tatsächlich zu einer langsameren Laufzeit Ihres Programms führt, verwenden Sie einen schrecklichen Compiler.
In Bezug auf die Komplexität der Betriebszeit sind die beiden Methoden (auch wenn tatsächlich eine Kopie ausgeführt wird) gleichwertig. Die Anzahl der Befehle, die innerhalb der Schleife ausgeführt werden, sollte die Anzahl der Operationen in der Inkrementierungsoperation erheblich dominieren. Daher wird in jeder Schleife von signifikanter Größe die Strafe der Inkrementierungsmethode durch die Ausführung des Schleifenkörpers massiv überschattet. Mit anderen Worten, Sie sollten sich viel besser Gedanken über die Optimierung des Codes in der Schleife machen als über das Inkrement.
Meiner Meinung nach läuft das ganze Thema einfach auf eine Stilpräferenz hinaus. Wenn Sie der Meinung sind, dass das Vorinkrement besser lesbar ist, verwenden Sie es. Persönlich bevorzuge ich das Post-Inkrement, aber das liegt wahrscheinlich daran, dass es mir beigebracht wurde, bevor ich etwas über Optimierung wusste.
Dies ist ein typisches Beispiel für vorzeitige Optimierung, und Probleme wie dieses können uns von schwerwiegenden Designproblemen ablenken. Es ist jedoch immer noch eine gute Frage, da es in "Best Practice" keine einheitliche Verwendung oder keinen einheitlichen Konsens gibt.
quelle
Beide erhöhen die Zahl.
++i
ist äquivalent zui = i + 1
.i++
und++i
sind sehr ähnlich, aber nicht genau gleich. Beide erhöhen die Zahl,++i
erhöhen jedoch die Zahl, bevor der aktuelle Ausdruck ausgewertet wird, währendi++
die Zahl erhöht wird, nachdem der Ausdruck ausgewertet wurde.Beispiel:
quelle
++i
(Prefix Betrieb): Inkremente und dann den Wert zuweist(z):
int i = 5
,int b = ++i
In diesem Fall wird zunächst 6 bis b zugeordnet und inkrementiert dann bis 7 und so weiter.i++
(Postfix - Betrieb): Ordnet und dann den Wert inkrementiert(z):
int i = 5
,int b = i++
In diesem Fall wird zunächst 5 bis b zugeordnet und inkrementiert dann bis 6 und so weiter.Incase of for-Schleife:
i++
wird meistens verwendet, da normalerweise der Startwert von verwendet wird,i
bevor die for-Schleife erhöht wird. Abhängig von Ihrer Programmlogik kann dies jedoch variieren.quelle
++i
: ist Pre-Inkrement, das andere ist Post-Inkrement.i++
: holt das Element und erhöht es dann.++i
: erhöht i und gibt dann das Element zurück.Beispiel:
Ausgabe:
quelle
Ich gehe davon aus, dass Sie den Unterschied in der Semantik jetzt verstehen (obwohl ich mich ehrlich frage, warum die Leute Fragen zum Stapelüberlauf stellen, anstatt zu lesen, wissen Sie, ein Buch oder ein Web-Tutorial oder so.
Ignorieren Sie jedoch die Leistungsfragen, die selbst in C ++ unwahrscheinlich sind. Dies ist das Prinzip, das Sie bei der Entscheidung verwenden sollten:
Sagen Sie, was Sie im Code meinen.
Wenn Sie den Wert vor dem Inkrement in Ihrer Anweisung nicht benötigen, verwenden Sie diese Form des Operators nicht. Es ist ein kleines Problem, aber wenn Sie nicht mit einem Styleguide arbeiten, der eine Version zugunsten der anderen verbietet (auch bekannt als knochenköpfiger Styleguide), sollten Sie das Formular verwenden, das am genauesten ausdrückt, was Sie tun möchten.
QED, verwenden Sie die Pre-Inkrement-Version:
quelle
Der Unterschied kann durch diesen einfachen C ++ - Code unten verstanden werden:
quelle
quelle
i ++ und ++ i
Dieser kleine Code kann helfen, den Unterschied aus einem anderen Blickwinkel als die bereits veröffentlichten Antworten zu visualisieren:
Das Ergebnis ist:
Achten Sie auf die Vorher- und Nachher-Situationen.
für Schleife
Ich denke, dass eines davon in einem Inkrementierungsblock einer for-Schleife verwendet werden sollte. Das Beste, was wir tun können, um eine Entscheidung zu treffen, ist ein gutes Beispiel:
Das Ergebnis ist:
Ich weiß nichts über dich, aber ich sehe keinen Unterschied in der Verwendung, zumindest in einer for-Schleife.
quelle
Das folgende C-Code-Fragment veranschaulicht den Unterschied zwischen den Operatoren vor und nach dem Inkrementieren und Dekrementieren:
Inkrementoperatoren:
quelle
Vorkrementieren bedeutet Inkrementieren in derselben Zeile. Nachinkrement bedeutet Inkrement nach Ausführung der Zeile.
Wenn es um OR- UND AND-Operatoren geht, wird es interessanter.
In Array
In C ++ Post / Pre-Inkrement der Zeigervariable
quelle
In Kürze:
++i
undi++
funktioniert genauso, wenn Sie sie nicht in eine Funktion schreiben. Wenn Sie so etwas verwendenfunction(i++)
oder sehenfunction(++i)
Sie den Unterschied.function(++i)
sagt erstes Inkrement i um 1, danach setze diesi
in die Funktion mit neuem Wert.function(i++)
sagt setzen zuersti
in die Funktion nach diesem Inkrementi
um 1.quelle
int j = ++i;
undint k = i++;
selbst wenn kein Funktionsaufruf beteiligt ist.Der einzige Unterschied besteht in der Reihenfolge der Operationen zwischen dem Inkrement der Variablen und dem vom Operator zurückgegebenen Wert.
Dieser Code und seine Ausgabe erklären den Unterschied:
Ausgabe ist:
++i
Gibt den Wert also grundsätzlich nach dem Inkrementieren zurück, während++i
der Wert vor dem Inkrementieren zurückgegeben wird. Am Ende wird in beiden Fällen deri
Wert des Willens erhöht.Ein anderes Beispiel:
Ausgabe:
Oft gibt es keinen Unterschied
Unterschiede sind deutlich , wenn der zurückgegebene Wert einer anderen Variablen zugeordnet ist oder wenn das Inkrement in Verkettung mit anderen Operationen durchgeführt wird , in dem Operationen Vorrang angewendet wird (
i++*2
verschieden von++i*2
, aber ,(i++)*2
und(++i)*2
gibt den gleichen Wert) , in vielen Fällen sind sie untereinander austauschbar. Ein klassisches Beispiel ist die for-Schleifensyntax:hat den gleichen Effekt von
Regel zum Erinnern
Um keine Verwechslung zwischen den beiden Operatoren zu machen, habe ich diese Regel übernommen:
Ordnen Sie die Position des Operators
++
in Bezug auf die Variablei
der Reihenfolge der++
Operation in Bezug auf die Zuordnung zuMit anderen Worten gesagt:
++
vori
bedeutet, dass die Inkrementierung vor der Zuweisung durchgeführt werden muss ;++
Afteri
bedeutet Inkrementierung muss nach Zuordnung durchgeführt werden :quelle
Sie können sich die interne Konvertierung als mehrere Anweisungen vorstellen.
Sie können es denken als,
Sie können es denken als,
quelle
a = i ++ bedeutet, dass a den aktuellen i-Wert enthält. a = ++ i bedeutet, dass a einen inkrementierten i-Wert enthält
quelle
a = i++;
bedeutet, dass der in gespeicherte Werta
der Werti
vor dem Inkrement ist, aber "ohne Inkrementieren" impliziert, dassi
nicht inkrementiert wird, was völlig falsch ist -i
inkrementiert wird, aber der Wert des Ausdrucks der Wert vor dem Inkrement ist.Hier ist das Beispiel, um den Unterschied zu verstehen
Ausgabe:
10 12/11 11
(abhängig von der Reihenfolge der Auswertung der Argumente für dieprintf
Funktion, die je nach Compiler und Architektur variiert)Erläuterung:
i++
->i
wird gedruckt und dann erhöht. (Druckt 10, wird aberi
zu 11)++i
->i
Wert erhöht und druckt den Wert. (Druckt 12 und den Wert voni
auch 12)quelle
i++
und++i