Care este diferența dintre ++i și i++? (Programare, C, Pentru Buclă, Post Increment, Pre Increment)

The.Anti.9 a intrebat.

În C, care este diferența dintre utilizarea ++i și i++, , și care ar trebui să fie utilizat în blocul de incrementare al unui fișier for buclă?

Comentarii

  • Nu sunt sigur că autorul inițial este interesat, dar în C++ diferența de performanță poate fi substanțială, deoarece crearea obiectului temporar poate fi costisitoare pentru un tip definit de utilizator. –  > Por Pe Freund.
21 răspunsuri
Mark Harrison
  • ++i va incrementa valoarea lui i, , și apoi va returna valoarea incrementată.

     i = 1;
     j = ++i;
     (i is 2, j is 2)
    
  • i++ va incrementa valoarea lui i, , dar va returna valoarea inițială care i a avut înainte de a fi incrementată.

     i = 1;
     j = i++;
     (i is 2, j is 1)
    

Pentru o valoare for ambele variante funcționează. ++i pare mai frecventă, poate pentru că așa se folosește în K&R.

În orice caz, urmați indicația „preferați ++i în loc de i++” și nu veți da greș.

Există câteva comentarii cu privire la eficiența ++i și i++. În orice compilator care nu este un proiect studențesc, nu va exista nicio diferență de performanță. Puteți verifica acest lucru uitându-vă la codul generat, care va fi identic.

Întrebarea privind eficiența este interesantă… iată încercarea mea de a răspunde: Există o diferență de performanță între i++ și ++i în C?

După cum remarcă @OnFreund, este diferit pentru un obiect C++, deoarece operator++() este o funcție și compilatorul nu poate ști să optimizeze crearea unui obiect temporar pentru a păstra valoarea intermediară.

Comentarii

  • Nu va avea acest efect vremea în care bucla se execută încă o dată la atingerea condiției finale? De exemplu, for(int i=0; i<10; i++){ print i; } nu va fi diferit de for(int i=0; i<10; ++i){ print i; } Din câte am înțeles, unele limbaje vor da rezultate diferite în funcție de cel pe care îl folosiți. –  > Por aVeRTRAC.
  • 33

  • jonnyflash, ambele vor funcționa identic, deoarece incrementarea lui i și imprimarea se află în instrucțiuni diferite. Acest lucru ar trebui să fie valabil pentru orice limbaj care acceptă ++ în stil C. Singura diferență între ++i și i++ va fi atunci când se utilizează valoarea operației în aceeași instrucțiune. –  > Por Mark Harrison.
  • 18

  • Deoarece în majoritatea cazurilor produc cod identic, prefer i++ deoarece are forma „operand-operator”, la fel ca o atribuire „operand-operator-valoare”. Cu alte cuvinte, operandul țintă se află în partea stângă a expresiei, la fel ca în cazul unei instrucțiuni de atribuire. –  > Por David R Tribble.
  • @MarkHarrison, va funcționa în mod identic nu pentru că i++ și print i sunt în instrucțiuni diferite, ci pentru că i++; și i<10 sunt. Observația lui @jonnyflash nu este atât de deplasată. Să presupunem că aveți for(int i=0; i++<10){ print i; } și for(int i=0; ++i<10){ print i; }. Acestea vor funcționa diferit în modul descris de @johnnyflash în primul comentariu. –  > Por Adam.
  • @sam, deoarece într-o buclă for tipică nu există niciun efect secundar (de exemplu, o atribuire) în partea ++i. –  > Por Mark Harrison.
Parag

i++ este cunoscut sub numele de Post Increment în timp ce ++i se numește Pre Increment.

i++

i++ este postincrementare deoarece incrementează icu 1 după terminarea operației.

Să vedem următorul exemplu:

int i = 1, j;
j = i++;

Aici valoarea lui j = 1 dar i = 2. Aici valoarea lui i va fi atribuită la j mai întâi, apoi i va fi incrementată.

++i

++i este preincrementare, deoarece incrementează icu 1 înainte de operație.Aceasta înseamnă că j = i; se va executa după ce i++.

Să vedem următorul exemplu:

int i = 1, j;
j = ++i;

Aici valoarea lui j = 2 dar i = 2. Aici valoarea lui i va fi atribuită la j după ce i creșterea lui i.în mod similar ++i va fi executată înainte de j=i;.

Pentru întrebarea dvs. care ar trebui să fie utilizat în blocul de incrementare al unei bucle for? răspunsul este că puteți folosi oricare dintre ele… nu contează. Se va executa bucla for de același număr de ori.

for(i=0; i<5; i++)
   printf("%d ",i);

Și

for(i=0; i<5; ++i)
   printf("%d ",i);

Ambele bucle vor produce același rezultat. adică 0 1 2 3 4.

Contează doar locul în care îl utilizați.

for(i = 0; i<5;)
    printf("%d ",++i);

În acest caz, rezultatul va fi 1 2 3 4 5.

Comentarii

  • Inițializarea variabilelor după prefix și post-fix ajută la înțelegere. Vă mulțumim. –  > Por Abdul Alim Shakir.
Andy Lester

Vă rugăm să nu vă faceți griji cu privire la „eficiența” (viteza, de fapt) care dintre ele este mai rapidă. Avem compilatoare în zilele noastre care se ocupă de aceste lucruri. Folosiți-o pe cea care are sens să o folosiți, în funcție de care vă arată mai clar intenția.

Comentarii

  • ceea ce, sper, înseamnăfolosiți prefixul (inc|dec)rement, cu excepția cazului în care aveți nevoie de fapt de vechea valoare înainte de (inc|dec), lucru pe care foarte puțini oameni îl fac, și totuși pe care o proporție năucitoare de presupuse materiale didactice îl folosesc, creând un cult cargo al utilizatorilor de postfix care nici măcar nu știu ce este‘..! –  > Por underscore_d.
  • Nu sunt sigur că „compilatoarele din zilele noastre … au grijă de aceste lucruri” este universal adevărat. În cadrul unui program personalizat operator++(int) (versiunea postfix), codul trebuie să creeze destul de mult un temporar care va fi returnat. Sunteți sigur că compilatoarele pot optimiza întotdeauna acest lucru? –  > Por Peter – Reinstaurați-o pe Monica.
Ryan Fox

++i incrementează valoarea, apoi o returnează.

i++ returnează valoarea, apoi o incrementează.

Este o diferență subtilă.

Pentru o buclă for, utilizați ++i, deoarece este puțin mai rapidă. i++ va crea o copie suplimentară care va fi aruncată.

Comentarii

    25

  • Nu cunosc niciun compilator în care să existe o diferență, cel puțin în cazul numerelor întregi. –  > Por blabla999.
  • Este nu mai rapid. Valorile sunt ignorate (doar efectul secundar este eficient) și compilatorul poate/va genera exact același cod. –  > Por wildplasser.
Shivprasad Koirala

i++: În acest scenariu, mai întâi se atribuie valoarea și apoi are loc incrementarea.

++i: În acest scenariu mai întâi se face incrementarea și apoi se atribuie valoarea

Mai jos este vizualizarea imaginii și, de asemenea aici este un video practic și frumos care demonstrează același lucru.

Comentarii

  • Cum puteți incrementa o valoare oarecum neatribuită? –  > Por kouty.
  • @kouty Puteți incrementa un registru neatribuit unei variabile. –  > Por Polluks.
OysterD

Motivul ++i poate să fie puțin mai rapid decât i++ este că i++ poate necesita o copie locală a valorii lui i înainte de a fi incrementată, în timp ce ++i nu o face niciodată. În unele cazuri, unele compilatoare vor optimiza acest lucru dacă este posibil… dar nu este întotdeauna posibil și nu toate compilatoarele fac acest lucru.

Eu încerc să nu mă bazez prea mult pe optimizările compilatoarelor, așa că aș urma sfatul lui Ryan Fox: atunci când pot folosi ambele, folosesc ++i.

Comentarii

  • -1 pentru C++ răspuns la întrebarea C. Nu mai există o „copie locală” a valorii lui i decât există a valorii 1 atunci când scrieți o instrucțiune 1;. –  > Por R.. GitHub NU MAI AJUTAȚI ICE.
dusktreader

Rezultatul efectiv al utilizării oricăruia dintre ele într-o buclă este identic. Cu alte cuvinte, bucla va face exact același lucru în ambele cazuri.

Din punct de vedere al eficienței, ar putea exista o penalizare implicată în alegerea lui i++ în locul lui ++i. În ceea ce privește specificațiile limbajului, utilizarea operatorului post-increment ar trebui să creeze o copie suplimentară a valorii asupra căreia acționează operatorul. Aceasta ar putea fi o sursă de operații suplimentare.

Cu toate acestea, ar trebui să luați în considerare două probleme principale legate de logica anterioară.

  1. Compilatoarele moderne sunt grozave. Toate compilatoarele bune sunt suficient de inteligente pentru a-și da seama că văd o creștere de număr întreg într-o buclă for-loop și vor optimiza ambele metode pentru a obține același cod eficient. Dacă utilizarea post-incrementului în locul pre-incrementului face ca programul dvs. să aibă un timp de execuție mai lent, atunci folosiți o metodă teribil compilator.

  2. În ceea ce privește complexitatea operațională a timpului, cele două metode (chiar dacă se efectuează efectiv o copie) sunt echivalente. Numărul de instrucțiuni care se execută în interiorul buclei ar trebui să domine semnificativ numărul de operații din operația de incrementare. Prin urmare, în orice buclă de dimensiuni semnificative, penalizarea metodei de incrementare va fi masiv umbrită de execuția corpului buclei. Cu alte cuvinte, este mult mai bine să vă preocupați de optimizarea codului din buclă decât de incrementare.

În opinia mea, întreaga problemă se reduce pur și simplu la o preferință de stil. Dacă credeți că pre-incrementul este mai ușor de citit, atunci folosiți-l. Personal, prefer post-incrementul, dar asta probabil pentru că așa am fost învățat înainte de a ști ceva despre optimizare.

Acesta este un exemplu chintesențial de optimizare prematură, iar problemele de acest gen au potențialul de a ne distrage atenția de la problemele serioase din proiectare. Cu toate acestea, este totuși o întrebare bună de pus, deoarece nu există o uniformitate în utilizare sau un consens în ceea ce privește „cele mai bune practici”.

Usman

Amândouă cresc numărul. ++i este echivalent cu i = i + 1.

i++ și ++i sunt foarte asemănătoare, dar nu sunt exact la fel. Ambele măresc numărul, dar ++i incrementează numărul înainte ca expresia curentă să fie evaluată, în timp ce i++ incrementează numărul după ce expresia este evaluată.

Exemplu:

int i = 1;
int x = i++; //x is 1, i is 2
int y = ++i; //y is 3, i is 3

Anands23

++i (operație de prefixare): Incrementă și apoi atribuie valoarea
(de exemplu): int i = 5, , int b = ++i În acest caz, 6 este atribuit mai întâi lui b și apoi se incrementează la 7 și așa mai departe.

i++ (Operația postfix): Atribuie și apoi incrementează valoarea
(de exemplu): int i = 5, , int b = i++ În acest caz, 5 este atribuit mai întâi lui b și apoi se incrementează la 6 și așa mai departe.

În cazul buclei for: i++ este utilizat în principal pentru că, în mod normal, folosim valoarea inițială a lui i înainte de a fi incrementată în bucla for. Dar, în funcție de logica programului dumneavoastră, aceasta poate varia.

Francesco Boi

Singura diferență este ordinea operațiilor între incrementarea variabilei și valoarea pe care o returnează operatorul.

Acest cod și rezultatul său explică diferența:

#include<stdio.h>

int main(int argc, char* argv[])
{
  unsigned int i=0, a;
  printf("i initial value: %d; ", i);
  a = i++;
  printf("value returned by i++: %d, i after: %d
", a, i);
  i=0;
  printf("i initial value: %d; ", i);
  a = ++i;
  printf(" value returned by ++i: %d, i after: %d
",a, i);
}

Ieșirea este:

i initial value: 0; value returned by i++: 0, i after: 1
i initial value: 0;  value returned by ++i: 1, i after: 1

Deci, în principiu ++i returnează valoarea după ce a fost incrementată, în timp ce i++ returnează valoarea înainte ca aceasta să fie incrementată. La sfârșit, în ambele cazuri, valoarea i va avea valoarea sa incrementată.

Un alt exemplu:

#include<stdio.h>

int main ()
  int i=0;
  int a = i++*2;
  printf("i=0, i++*2=%d
", a);
  i=0;
  a = ++i * 2;
  printf("i=0, ++i*2=%d
", a);
  i=0;
  a = (++i) * 2;
  printf("i=0, (++i)*2=%d
", a);
  i=0;
  a = (++i) * 2;
  printf("i=0, (++i)*2=%d
", a);
  return 0;
}

Output:

i=0, i++*2=0
i=0, ++i*2=2
i=0, (++i)*2=2
i=0, (++i)*2=2

De multe ori nu există nicio diferență

Diferențele sunt clare atunci când valoarea returnată este atribuită unei alte variabile sau atunci când incrementarea este efectuată în concatenare cu alte operații în care se aplică precedența operațiilor (i++*2 este diferită de ++i*2, , dar (i++)*2 și (++i)*2 returnează aceeași valoare), în multe cazuri acestea sunt interschimbabile. Un exemplu clasic este sintaxa buclei for:

for(int i=0; i<10; i++)

are același efect ca și

for(int i=0; i<10; ++i)

Regula de reținut

Pentru a nu face nicio confuzie între cei doi operatori am adoptat această regulă:

Asociați poziția operatorului ++ în raport cu variabila i la ordinea de ++ operației în raport cu atribuirea

Cu alte cuvinte:

  • ++ înainte de i înseamnă că trebuie efectuată incrementarea înainte de atribuirii;
  • ++ după i înseamnă că incrementarea trebuie să fie efectuată după atribuirea:

Scitech

++i: este pre-increment, iar celălalt este post-increment.

i++: obține elementul și apoi îl incrementează.
++i: incrementează i și apoi returnează elementul.

Exemplu:

int i = 0;
printf("i: %d
", i);
printf("i++: %d
", i++);
printf("++i: %d
", ++i);

Ieșire:

i: 0
i++: 0
++i: 2

carloswm85

i++ și ++i

Acest mic cod poate ajuta la vizualizarea diferenței dintr-un unghi diferit față de răspunsurile deja postate:

int i = 10, j = 10;
  
printf ("i is %i 
", i);
printf ("i++ is %i 
", i++);
printf ("i is %i 

", i);
  
printf ("j is %i 
", j);
printf ("++j is %i 
", ++j);
printf ("j is %i 
", j);

Rezultatul este:

//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 

Fiți atenți la situațiile înainte și după.

for loop

În ceea ce privește care dintre ele ar trebui să fie folosită într-un bloc de incrementare a unei bucle for, cred că cel mai bun lucru pe care îl putem face pentru a lua o decizie este să folosim un exemplu bun:

int i, j;

for (i = 0; i <= 3; i++)
    printf (" > iteration #%i", i);

printf ("
");

for (j = 0; j <= 3; ++j)
    printf (" > iteration #%i", j);

Rezultatul este:

> iteration #0 > iteration #1 > iteration #2 > iteration #3
> iteration #0 > iteration #1 > iteration #2 > iteration #3 

Nu știu ce părere aveți voi, dar eu nu văd nicio diferență în utilizarea sa, cel puțin într-o buclă for.

Comentarii

  • Un răspuns excelent. Alții au scris aceleași chestii copy paste sau coduri mai complexe. Știm cu toții (presupunând o expunere corectă la programare) termenii postfix și prefix, dar modul în care se va comporta poate fi înțeles cu adevărat prin intermediul pentru o buclă for. –  > Por Nikhil Arora.
Nihal Reddy

Următorul fragment de cod C ilustrează diferența dintre operatorii pre și post increment și decrement:

int  i;
int  j;

Operatori de incrementare:

i = 1;
j = ++i;    // i is now 2, j is also 2
j = i++;    // i is now 3, j is 2

Scott Urban

Presupun că acum înțelegeți diferența de semantică (deși, sincer, mă întreb de ce oamenii pun întrebări de genul „ce înseamnă operatorul X” pe stack overflow în loc să citească, știți, o carte sau un tutorial web sau ceva de genul acesta.

Dar, oricum, în ceea ce privește pe care să îl folosești, ignoră chestiunile legate de performanță, care nu sunt probabil importante nici măcar în C++. Acesta este principiul pe care ar trebui să îl folosiți atunci când decideți pe care să îl folosiți:

Spuneți ce vreți să spuneți în cod.

Dacă nu aveți nevoie de „value-before-increment” în declarația dvs., nu folosiți această formă a operatorului. Este o problemă minoră, dar, dacă nu lucrați cu un ghid de stil care interzice una dintre versiuni în favoarea celeilalte cu totul (aka un ghid de stil cu cap de os), ar trebui să folosiți forma care exprimă cel mai exact ceea ce încercați să faceți.

QED, folosiți varianta pre-increment:

for (int i = 0; i != X; ++i) ...

IOstream

Diferența poate fi înțeleasă cu ajutorul acestui simplu cod C++ de mai jos:

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;

Gopinath Kaliappan

Principala diferență este

  • i++ Post(După incrementare) și
  • ++i Pre (Înainte de creștere)

    • post dacă i =1 bucla se incrementează ca 1,2,3,4,n
    • pre dacă i =1 bucla se incrementează ca 2,3,4,5,n

Uddhav Gautam

Pre-crement înseamnă incrementare pe aceeași linie. Post-increment înseamnă incrementare după ce linia se execută.

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

Când vine vorba de operatorii OR, AND, devine mai interesant.

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
}

În 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 ( "
%d %d %d
", ii, jj, mm ) ; //12, 12, 13

for (int val: a) {
     System.out.print(" " +val); //55, 13, 15, 20, 25
}

În C++, post/pre-increment al variabilei pointer

#include <iostream>
using namespace std;

int main() {

    int x=10;
    int* p = &x;

    std::cout<<"address = "<<p<<"
"; //prints address of x
    std::cout<<"address = "<<p<<"
"; //prints (address of x) + sizeof(int)
    std::cout<<"address = "<<&x<<"
"; //prints address of x

    std::cout<<"address = "<<++&x<<"
"; //error. reference can't re-assign because it is fixed (immutable)
}

GokhanAvci

Pe scurt:

++i și i++ funcționează la fel dacă nu le scrieți într-o funcție. Dacă folosiți ceva de genul function(i++) sau function(++i) puteți vedea diferența.

function(++i) spune că mai întâi incrementează i cu 1, după care puneți acest lucru i în funcție cu noua valoare.

function(i++) spune că pune mai întâi i în funcție, după care crește i cu 1.

int i=4;
printf("%d
",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

Comentarii

  • Diferența nu este cu adevărat legată de apelurile de funcție (și puteți observa diferența fără a face apeluri de funcție). Există o diferență între int j = ++i; și int k = i++; chiar și atunci când nu este implicat niciun apel de funcție. –  > Por Jonathan Leffler.
Jeet Parikh

Vă puteți gândi la conversia internă a acesteia ca la o declarații multiple;

  • cazul 1
i++;

vă puteți gândi ca,

i;
i = i+1;
  • cazul 2
++i;

puteți gândi ca,

i = i+i;
i;

munna

a=i++ înseamnă că a conține valoarea i curentăa=++i înseamnă că a conține valoarea i incrementată.

Comentarii

  • Acest răspuns nu este corect. a = i++; înseamnă că valoarea stocată în a va fi valoarea lui i înainte de incrementare, dar „fără incrementare” implică faptul că i nu este incrementată, ceea ce este complet greșit – i este incrementată, dar valoarea expresiei este valoarea de dinaintea incrementării. –  > Por Jonathan Leffler.
srinath

Iată un exemplu pentru a înțelege diferența

int i=10;
printf("%d %d",i++,++i);

ieșire: 10 12/11 11 (în funcție de ordinea de evaluare a argumentelor pentru printf care variază în funcție de compilatoare și arhitecturi)

Explicație:i++->i se tipărește și apoi se incrementează. (Se tipărește 10, dar i va deveni 11)++i->i valoarea se incrementează și se tipărește valoarea. (Se tipărește 12, iar valoarea de i de asemenea 12)

Comentarii

  • Acest lucru determină un comportament nedefinit, deoarece nu există un punct de secvență între i++ și ++i –  > Por M.M.
  • @Lundin este corect, totuși, LHS, RHS de virgulă au un punct de secvență între ele, dar cele 2 expresii sunt încă nesecvențiate una față de cealaltă –  > Por Antti Haapala.