In C, qual è la differenza tra l'utilizzo di ++i
e i++
, e quale dovrebbe essere usato nel blocco di incremento di un for
ciclo?
In C, qual è la differenza tra l'utilizzo di ++i
e i++
, e quale dovrebbe essere usato nel blocco di incremento di un for
ciclo?
Risposte:
++i
incrementerà il valore di i
e quindi restituirà il valore incrementato.
i = 1;
j = ++i;
(i is 2, j is 2)
i++
incrementerà il valore di i
, ma restituirà il valore originale i
conservato prima di essere incrementato.
i = 1;
j = i++;
(i is 2, j is 1)
Per un for
ciclo, entrambi funzionano. ++i
sembra più comune, forse perché è quello che viene utilizzato in K&R .
In ogni caso, seguire le linee guida "preferiscono ++i
over i++
" e non andrà male.
Ci sono un paio di commenti sull'efficienza di ++i
e i++
. In qualsiasi compilatore per progetto non studente, non ci saranno differenze di prestazioni. Puoi verificarlo guardando il codice generato, che sarà identico.
La domanda di efficienza è interessante ... ecco il mio tentativo di risposta: c'è una differenza di prestazioni tra i ++ e ++ i in C?
Come osserva @OnFreund , è diverso per un oggetto C ++, poiché operator++()
è una funzione e il compilatore non può sapere di ottimizzare la creazione di un oggetto temporaneo per contenere il valore intermedio.
for(int i=0; i<10; i++){ print i; }
questo non sarà diverso dalla for(int i=0; i<10; ++i){ print i; }
mia comprensione è che alcune lingue ti daranno risultati diversi a seconda di quale usi.
i++
perché è nella forma "operando-operatore", come un "operando-operatore-valore". In altre parole, l'operando target si trova sul lato sinistro dell'espressione, proprio come in un'istruzione di assegnazione.
i++
e print i
siano in dichiarazioni diverse, ma perché i++;
e lo i<10
sono. L'osservazione di @ jonnyflash non è così off base. Supponiamo di avere for(int i=0; i++<10){ print i; }
e for(int i=0; ++i<10){ print i; }
. Funzioneranno diversamente nel modo descritto da @johnnyflash nel primo commento.
i ++ è noto come Post Increment mentre ++ i è chiamato Pre Increment.
i++
i++
è post incremento perché incrementa i
il valore di 1 al termine dell'operazione.
Vediamo il seguente esempio:
int i = 1, j;
j = i++;
Qui valore di j = 1
ma i = 2
. Qui il valore di i
verrà assegnato per j
primo, quindi i
verrà incrementato.
++i
++i
è pre-incremento perché incrementa i
il valore di 1 prima dell'operazione. Significa che j = i;
verrà eseguito dopo i++
.
Vediamo il seguente esempio:
int i = 1, j;
j = ++i;
Qui valore di j = 2
ma i = 2
. Qui i
verrà assegnato il valore di j
dopo l' i
incremento di i
. Allo stesso modo ++i
verrà eseguito prima j=i;
.
Per la tua domanda quale dovrebbe essere usato nel blocco di incremento di un ciclo for? la risposta è che puoi usare chiunque .. non importa. Eseguirà il tuo ciclo for lo stesso no. di volte.
for(i=0; i<5; i++)
printf("%d ",i);
E
for(i=0; i<5; ++i)
printf("%d ",i);
Entrambi i loop produrranno lo stesso output. vale a dire 0 1 2 3 4
.
Importa solo dove lo stai usando.
for(i = 0; i<5;)
printf("%d ",++i);
In questo caso l'output sarà 1 2 3 4 5
.
Per favore, non preoccuparti dell '"efficienza" (velocità, davvero) di cui uno è più veloce. Oggi abbiamo compilatori che si occupano di queste cose. Usa quello che ha senso usare, in base al quale mostra più chiaramente le tue intenzioni.
operator++(int)
(la versione postfix) il codice deve praticamente creare un temporaneo che verrà restituito. Sei sicuro che i compilatori possano sempre ottimizzarlo?
++i
incrementa il valore, quindi lo restituisce.
i++
restituisce il valore e quindi lo incrementa.
È una differenza sottile.
Per un ciclo for, usa ++i
, poiché è leggermente più veloce. i++
creerà una copia extra che viene semplicemente gettata via.
i++
: In questo scenario viene prima assegnato il valore e poi si verifica l'incremento.
++i
: In questo scenario prima viene eseguito l'incremento e quindi viene assegnato il valore
Di seguito è riportata la visualizzazione delle immagini e anche qui è un bel video pratico che dimostra lo stesso.
Il motivo ++i
può essere leggermente più veloce di quello i++
che i++
può richiedere una copia locale del valore di i prima che venga incrementato, mentre ++i
non lo fa mai. In alcuni casi, alcuni compilatori lo ottimizzeranno se possibile ... ma non è sempre possibile, e non tutti i compilatori lo fanno.
Cerco di non fare troppo affidamento sulle ottimizzazioni dei compilatori, quindi seguirò i consigli di Ryan Fox: quando posso usare entrambi, li uso ++i
.
i
quanto non lo sia del valore 1 quando si scrive un'istruzione 1;
.
Il risultato effettivo dell'uso di entrambi in un ciclo è identico. In altre parole, il loop farà la stessa cosa esatta in entrambi i casi.
In termini di efficienza, potrebbe esserci una penalità per la scelta di i ++ su ++ i. In termini di specifiche della lingua, l'uso dell'operatore post-incremento dovrebbe creare una copia aggiuntiva del valore su cui l'operatore agisce. Questo potrebbe essere una fonte di operazioni extra.
Tuttavia, è necessario considerare due problemi principali con la logica precedente.
I compilatori moderni sono fantastici. Tutti i buoni compilatori sono abbastanza intelligenti da rendersi conto che sta vedendo un incremento intero in un ciclo for e ottimizzerà entrambi i metodi con lo stesso codice efficiente. Se l'uso di post-incremento su pre-incremento provoca effettivamente un tempo di esecuzione più lento del programma, allora stai usando un compilatore terribile .
In termini di complessità temporale operativa, i due metodi (anche se una copia viene effettivamente eseguita) sono equivalenti. Il numero di istruzioni eseguite all'interno del loop dovrebbe dominare in modo significativo il numero di operazioni nell'operazione di incremento. Pertanto, in qualsiasi loop di dimensioni significative, la penalità del metodo di incremento verrà enormemente messa in ombra dall'esecuzione del corpo del loop. In altre parole, è molto meglio preoccuparsi di ottimizzare il codice nel ciclo piuttosto che l'incremento.
Secondo me, l'intera questione si riduce semplicemente a una preferenza di stile. Se ritieni che il pre-incremento sia più leggibile, allora usalo. Personalmente preferisco il post-incremento, ma probabilmente è perché era quello che mi era stato insegnato prima di sapere qualcosa sull'ottimizzazione.
Questo è un esempio per eccellenza di ottimizzazione prematura e problemi come questo hanno il potenziale per distrarci da gravi problemi di progettazione. È comunque una buona domanda da porre, poiché non vi è uniformità nell'uso o consenso nelle "migliori pratiche".
Entrambi incrementano il numero. ++i
è equivalente a i = i + 1
.
i++
e ++i
sono molto simili ma non esattamente uguali. Entrambi incrementano il numero, ma ++i
incrementa il numero prima che venga valutata l'espressione corrente, mentre i++
incrementa il numero dopo la valutazione dell'espressione.
Esempio:
int i = 1;
int x = i++; //x is 1, i is 2
int y = ++i; //y is 3, i is 3
++i
(Funzionamento prefisso): Si aggiunge quindi assegna il valore
(es): int i = 5
, int b = ++i
in questo caso, 6 viene assegnato B primo e poi lentamente per 7 e così via.
i++
(Funzionamento Postfix): attribuisce e quindi incrementa il valore
(es): int i = 5
, int b = i++
in questo caso, 5 appartiene alla B primo e poi lentamente per 6 e così via.
Incase di for loop: i++
è usato principalmente perché, normalmente usiamo il valore iniziale di i
prima di incrementare in for loop. Ma a seconda della logica del programma può variare.
Presumo che tu capisca la differenza nella semantica ora (anche se onestamente mi chiedo perché la gente faccia domande "cosa significa l'operatore X" sullo stack overflow piuttosto che leggere, sai, un libro o un tutorial web o qualcosa del genere.
Ma comunque, per quanto riguarda quello da usare, ignora le domande di prestazione, che sono improbabili importanti anche in C ++. Questo è il principio che dovresti usare quando decidi quale usare:
Dì cosa intendi nel codice.
Se non hai bisogno del valore prima dell'incremento nella tua dichiarazione, non utilizzare quella forma di operatore. È un problema minore, ma a meno che tu non stia lavorando con una guida di stile che vieta una versione a favore dell'altra (alias una guida di stile dalla testa d'osso), dovresti usare il modulo che esprime più esattamente ciò che stai cercando di fare.
QED, utilizzare la versione pre-incremento:
for (int i = 0; i != X; ++i) ...
La differenza può essere compresa da questo semplice codice C ++ di seguito:
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;
La differenza principale è
- i ++ Post ( dopo l'incremento ) e
++ i Pre ( prima dell'incremento )
- pubblica se
i =1
il ciclo aumenta come1,2,3,4,n
- pre se
i =1
il ciclo aumenta come2,3,4,5,n
Questo piccolo codice può aiutare a visualizzare la differenza da un'angolazione diversa rispetto alle risposte già pubblicate:
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);
Il risultato è:
//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
Prestare attenzione alle situazioni prima e dopo.
Per quanto riguarda quale di questi dovrebbe essere usato in un blocco di incremento di un ciclo for, penso che il meglio che possiamo fare per prendere una decisione sia usare un buon esempio:
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);
Il risultato è:
> iteration #0 > iteration #1 > iteration #2 > iteration #3
> iteration #0 > iteration #1 > iteration #2 > iteration #3
Non ti conosco, ma non vedo alcuna differenza nel suo utilizzo, almeno in un ciclo for.
Il seguente frammento di codice C illustra la differenza tra gli operatori di incremento e decremento pre e post:
int i;
int j;
Incrementare gli operatori:
i = 1;
j = ++i; // i is now 2, j is also 2
j = i++; // i is now 3, j is 2
Pre-crement significa incremento sulla stessa riga. Post-incremento significa incremento dopo l'esecuzione della riga.
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
Quando si tratta di operatori OR, AND, diventa più interessante.
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 matrice
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-incremento della variabile puntatore
#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 breve:
++i
e i++
funziona allo stesso modo se non li stai scrivendo in una funzione. Se usi qualcosa come function(i++)
ofunction(++i)
puoi vedere la differenza.
function(++i)
dice il primo incremento i di 1, dopodiché mettilo i
nella funzione con un nuovo valore.
function(i++)
dice messo prima i
nella funzione dopo quell'incremento i
di 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;
e int k = i++;
anche quando non è coinvolta alcuna chiamata di funzione.
L'unica differenza è l'ordine delle operazioni tra l'incremento della variabile e il valore restituito dall'operatore.
Questo codice e il suo output spiegano la differenza:
#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);
}
L'output è:
i before: 1; value returned by i++: 0, i after: 1
i before: 1; value returned by ++i: 1, i after: 1
Quindi sostanzialmente ++i
restituisce il valore dopo che è stato incrementato, mentre ++i
restituisce il valore prima che sia incrementato. Alla fine, in entrambi i casi il i
valore sarà incrementato.
Un altro esempio:
#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;
}
Produzione:
i=0, i++*2=0
i=0, ++i*2=2
i=0, (++i)*2=2
i=0, (++i)*2=2
Le differenze sono chiare quando il valore restituito viene assegnato a un'altra variabile o quando l'incremento viene eseguito in concatenazione con altre operazioni in cui viene applicata la precedenza delle operazioni ( i++*2
è diversa da ++i*2
, (i++)*2
e (++i)*2
restituisce lo stesso valore) in molti casi sono intercambiabili. Un esempio classico è la sintassi del ciclo for:
for(int i=0; i<10; i++)
ha lo stesso effetto di
for(int i=0; i<10; ++i)
Per non creare confusione tra i due operatori ho adottato questa regola:
Associare la posizione dell'operatore ++
rispetto alla variabile i
all'ordine ++
dell'operazione rispetto all'assegnazione
Detto in altre parole:
++
prima i
significa che l'incremento deve essere effettuato prima dell'incarico;++
dopo i
significa che l'incremento deve essere effettuato dopo l' assegnazione:Puoi pensare alla conversione interna di ciò come a più dichiarazioni ;
i++;
puoi pensarlo come
i;
i = i+1;
++i;
puoi pensarlo come
i = i+i;
i;
a = i ++ indica che contiene un valore i corrente a = ++ i indica che contiene un valore i incrementato
a = i++;
significa che il valore memorizzato a
sarà il valore i
prima dell'incremento, ma "senza incremento" implica che i
non viene incrementato, il che è completamente sbagliato - i
viene incrementato, ma il valore dell'espressione è il valore prima dell'incremento.
Ecco l'esempio per capire la differenza
int i=10;
printf("%d %d",i++,++i);
output: 10 12/11 11
(a seconda dell'ordine di valutazione degli argomenti per la printf
funzione, che varia tra compilatori e architetture)
Spiegazione:
i++
-> i
viene stampato, quindi viene incrementato. (Stampa 10, ma i
diventerà 11)
++i
-> i
incrementi di valore e stampa il valore. (Stampa 12 e valore i
anche di 12)
i++
e++i