Was ist in C der Unterschied zwischen der Verwendung von ++i
und i++
und welche sollte im Inkrementierungsblock einer for
Schleife verwendet werden?
Was ist in C der Unterschied zwischen der Verwendung von ++i
und i++
und welche sollte im Inkrementierungsblock einer for
Schleife verwendet werden?
Antworten:
++i
erhöht den Wert von i
und gibt dann den inkrementierten Wert zurück.
i = 1;
j = ++i;
(i is 2, j is 2)
i++
erhöht den Wert von i
, gibt jedoch den ursprünglichen Wert zurück, i
der vor dem Inkrementieren gehalten wurde.
i = 1;
j = i++;
(i is 2, j is 1)
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
als i++
" und Sie werden nichts falsch machen.
Es gibt ein paar Kommentare zur Effizienz von ++i
und i++
. 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.
for(int i=0; i<10; i++){ print i; }
Wird dies zum Beispiel nicht anders sein als for(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++
und print i
in verschiedenen Anweisungen sind, sondern weil i++;
und i<10
sind. @ jonnyflashs Bemerkung ist nicht so falsch. Angenommen, Sie haben for(int i=0; i++<10){ print i; }
und for(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 der i
Wert nach Abschluss der Operation um 1 erhöht wird.
Sehen wir uns das folgende Beispiel an:
int i = 1, j;
j = i++;
Hier Wert von j = 1
aber i = 2
. Hier wird zuerst der Wert von i
zugewiesen und j
dann i
erhöht.
++i
++i
ist vor dem Inkrementieren, da der i
Wert vor der Operation um 1 erhöht wird . Es bedeutet, j = i;
wird nach ausgeführt i++
.
Sehen wir uns das folgende Beispiel an:
int i = 1, j;
j = ++i;
Hier Wert von j = 2
aber i = 2
. Hier i
wird j
nach dem i
Inkrementieren von der Wert von zugewiesen i
. Ebenso ++i
wird vorher ausgeführt j=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.
for(i=0; i<5; i++)
printf("%d ",i);
Und
for(i=0; i<5; ++i)
printf("%d ",i);
Beide Schleifen erzeugen die gleiche Ausgabe. dh 0 1 2 3 4
.
Es ist nur wichtig, wo Sie es verwenden.
for(i = 0; i<5;)
printf("%d ",++i);
In diesem Fall wird ausgegeben 1 2 3 4 5
.
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.
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.
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 zugewiesen
Unten ist die Bildvisualisierung und hier ist ein schönes praktisches Video , das dasselbe demonstriert.
Der Grund ++i
kann etwas schneller sein als der i++
, 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
.
i
als des Werts 1, wenn Sie eine Anweisung schreiben 1;
.
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.
Beide erhöhen die Zahl. ++i
ist äquivalent zu i = 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ährend i++
die Zahl erhöht wird, nachdem der Ausdruck ausgewertet wurde.
Beispiel:
int i = 1;
int x = i++; //x is 1, i is 2
int y = ++i; //y is 3, i is 3
++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.
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:
for (int i = 0; i != X; ++i) ...
Der Unterschied kann durch diesen einfachen C ++ - Code unten verstanden werden:
int i, j, k, l;
i = 1; //initialize int i with 1
j = i+1; //add 1 with i and set that as the value of j. i is still 1
k = i++; //k gets the current value of i, after that i is incremented. So here i is 2, but k is 1
l = ++i; // i is incremented first and then returned. So the value of i is 3 and so does l.
cout << i << ' ' << j << ' ' << k << ' '<< l << endl;
return 0;
Der Hauptunterschied ist
- i ++ Post ( nach Inkrementierung ) und
++ i Pre ( vor dem Inkrementieren )
- poste wenn
i =1
die Schleife wie inkrementiert1,2,3,4,n
- pre, wenn
i =1
die Schleife wie inkrementiert2,3,4,5,n
Dieser kleine Code kann helfen, den Unterschied aus einem anderen Blickwinkel als die bereits veröffentlichten Antworten zu visualisieren:
int i = 10, j = 10;
printf ("i is %i \n", i);
printf ("i++ is %i \n", i++);
printf ("i is %i \n\n", i);
printf ("j is %i \n", j);
printf ("++j is %i \n", ++j);
printf ("j is %i \n", j);
Das Ergebnis ist:
//Remember that the values are i = 10, and j = 10
i is 10
i++ is 10 //Assigns (print out), then increments
i is 11
j is 10
++j is 11 //Increments, then assigns (print out)
j is 11
Achten Sie auf die Vorher- und Nachher-Situationen.
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:
int i, j;
for (i = 0; i <= 3; i++)
printf (" > iteration #%i", i);
printf ("\n");
for (j = 0; j <= 3; ++j)
printf (" > iteration #%i", j);
Das Ergebnis ist:
> iteration #0 > iteration #1 > iteration #2 > iteration #3
> iteration #0 > iteration #1 > iteration #2 > iteration #3
Ich weiß nichts über dich, aber ich sehe keinen Unterschied in der Verwendung, zumindest in einer for-Schleife.
Das folgende C-Code-Fragment veranschaulicht den Unterschied zwischen den Operatoren vor und nach dem Inkrementieren und Dekrementieren:
int i;
int j;
Inkrementoperatoren:
i = 1;
j = ++i; // i is now 2, j is also 2
j = i++; // i is now 3, j is 2
Vorkrementieren bedeutet Inkrementieren in derselben Zeile. Nachinkrement bedeutet Inkrement nach Ausführung der Zeile.
int j=0;
System.out.println(j); //0
System.out.println(j++); //0. post-increment. It means after this line executes j increments.
int k=0;
System.out.println(k); //0
System.out.println(++k); //1. pre increment. It means it increments first and then the line executes
Wenn es um OR- UND AND-Operatoren geht, wird es interessanter.
int m=0;
if((m == 0 || m++ == 0) && (m++ == 1)) { //false
/* in OR condition if first line is already true then compiler doesn't check the rest. It is technique of compiler optimization */
System.out.println("post-increment "+m);
}
int n=0;
if((n == 0 || n++ == 0) && (++n == 1)) { //true
System.out.println("pre-increment "+n); //1
}
In Array
System.out.println("In Array");
int[] a = { 55, 11, 15, 20, 25 } ;
int ii, jj, kk = 1, mm;
ii = ++a[1]; // ii = 12. a[1] = a[1] + 1
System.out.println(a[1]); //12
jj = a[1]++; //12
System.out.println(a[1]); //a[1] = 13
mm = a[1];//13
System.out.printf ( "\n%d %d %d\n", ii, jj, mm ) ; //12, 12, 13
for (int val: a) {
System.out.print(" " +val); //55, 13, 15, 20, 25
}
In C ++ Post / Pre-Inkrement der Zeigervariable
#include <iostream>
using namespace std;
int main() {
int x=10;
int* p = &x;
std::cout<<"address = "<<p<<"\n"; //prints address of x
std::cout<<"address = "<<p<<"\n"; //prints (address of x) + sizeof(int)
std::cout<<"address = "<<&x<<"\n"; //prints address of x
std::cout<<"address = "<<++&x<<"\n"; //error. reference can't re-assign because it is fixed (immutable)
}
In Kürze:
++i
und i++
funktioniert genauso, wenn Sie sie nicht in eine Funktion schreiben. Wenn Sie so etwas verwenden function(i++)
oder sehen function(++i)
Sie den Unterschied.
function(++i)
sagt erstes Inkrement i um 1, danach setze dies i
in die Funktion mit neuem Wert.
function(i++)
sagt setzen zuerst i
in die Funktion nach diesem Inkrement i
um 1.
int i=4;
printf("%d\n",pow(++i,2));//it prints 25 and i is 5 now
i=4;
printf("%d",pow(i++,2));//it prints 16 i is 5 now
int j = ++i;
und int 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:
#include<stdio.h>
int main(int argc, char* argv[])
{
unsigned int i=0, a;
a = i++;
printf("i before: %d; value returned by i++: %d, i after: %d\n", i, a, i);
i=0;
a = ++i;
printf("i before: %d; value returned by ++i: %d, i after: %d\n", i, a, i);
}
Ausgabe ist:
i before: 1; value returned by i++: 0, i after: 1
i before: 1; value returned by ++i: 1, i after: 1
++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 der i
Wert des Willens erhöht.
Ein anderes Beispiel:
#include<stdio.h>
int main ()
int i=0;
int a = i++*2;
printf("i=0, i++*2=%d\n", a);
i=0;
a = ++i * 2;
printf("i=0, ++i*2=%d\n", a);
i=0;
a = (++i) * 2;
printf("i=0, (++i)*2=%d\n", a);
i=0;
a = (++i) * 2;
printf("i=0, (++i)*2=%d\n", a);
return 0;
}
Ausgabe:
i=0, i++*2=0
i=0, ++i*2=2
i=0, (++i)*2=2
i=0, (++i)*2=2
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:
for(int i=0; i<10; i++)
hat den gleichen Effekt von
for(int i=0; i<10; ++i)
Um keine Verwechslung zwischen den beiden Operatoren zu machen, habe ich diese Regel übernommen:
Ordnen Sie die Position des Operators ++
in Bezug auf die Variable i
der Reihenfolge der ++
Operation in Bezug auf die Zuordnung zu
Mit anderen Worten gesagt:
++
vor i
bedeutet, dass die Inkrementierung vor der Zuweisung durchgeführt werden muss ;++
After i
bedeutet Inkrementierung muss nach Zuordnung durchgeführt werden :Sie können sich die interne Konvertierung als mehrere Anweisungen vorstellen.
i++;
Sie können es denken als,
i;
i = i+1;
++i;
Sie können es denken als,
i = i+i;
i;
a = i ++ bedeutet, dass a den aktuellen i-Wert enthält. a = ++ i bedeutet, dass a einen inkrementierten i-Wert enthält
a = i++;
bedeutet, dass der in gespeicherte Wert a
der Wert i
vor dem Inkrement ist, aber "ohne Inkrementieren" impliziert, dass i
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
int i=10;
printf("%d %d",i++,++i);
Ausgabe: 10 12/11 11
(abhängig von der Reihenfolge der Auswertung der Argumente für die printf
Funktion, die je nach Compiler und Architektur variiert)
Erläuterung:
i++
-> i
wird gedruckt und dann erhöht. (Druckt 10, wird aber i
zu 11)
++i
-> i
Wert erhöht und druckt den Wert. (Druckt 12 und den Wert von i
auch 12)
i++
und++i