En C, quelle est la différence entre l'utilisation de ++i
et i++
, et laquelle doit être utilisée dans le bloc d'incrémentation d'une for
boucle?
En C, quelle est la différence entre l'utilisation de ++i
et i++
, et laquelle doit être utilisée dans le bloc d'incrémentation d'une for
boucle?
Réponses:
++i
incrémentera la valeur de i
, puis renverra la valeur incrémentée.
i = 1;
j = ++i;
(i is 2, j is 2)
i++
incrémentera la valeur de i
, mais renverra la valeur d'origine qui i
contenait avant d'être incrémentée.
i = 1;
j = i++;
(i is 2, j is 1)
Pour une for
boucle, l'un ou l'autre fonctionne. ++i
semble plus courant, peut-être parce que c'est ce qui est utilisé dans K&R .
Dans tous les cas, suivez la directive "préférez ++i
plutôt i++
" et vous ne vous tromperez pas.
Il y a quelques commentaires concernant l'efficacité de ++i
et i++
. Dans tout compilateur non étudiant-projet, il n'y aura aucune différence de performance. Vous pouvez le vérifier en regardant le code généré, qui sera identique.
La question de l'efficacité est intéressante ... voici ma tentative de réponse: y a-t-il une différence de performances entre i ++ et ++ i en C?
Comme le note @OnFreund , c'est différent pour un objet C ++, car il operator++()
s'agit d'une fonction et le compilateur ne peut pas savoir optimiser la création d'un objet temporaire pour contenir la valeur intermédiaire.
for(int i=0; i<10; i++){ print i; }
cela ne sera-t-il pas différent de for(int i=0; i<10; ++i){ print i; }
Ma compréhension est que certaines langues vous donneront des résultats différents en fonction de celui que vous utilisez.
i++
car il est de la forme "opérande-opérateur", à la manière d'une "opérande-opérateur-valeur". En d'autres termes, l'opérande cible est sur le côté gauche de l'expression, tout comme dans une instruction d'affectation.
i++
et print i
sont dans des déclarations différentes, mais parce que i++;
et i<10
sont. La remarque de @ jonnyflash n'est pas que hors de la base. Supposons que vous ayez for(int i=0; i++<10){ print i; }
et for(int i=0; ++i<10){ print i; }
. Ceux-ci fonctionneront différemment de la manière décrite par @johnnyflash dans le premier commentaire.
i ++ est connu comme Post Increment tandis que ++ i est appelé Pre Increment.
i++
i++
est post-incrément car il incrémente i
la valeur de 1 après la fin de l'opération.
Voyons l'exemple suivant:
int i = 1, j;
j = i++;
Voici la valeur de j = 1
mais i = 2
. Ici, la valeur de i
sera affectée à j
first puis i
sera incrémentée.
++i
++i
est pré-incrémenté car il incrémente i
la valeur de 1 avant l'opération. Cela signifie j = i;
s'exécutera après i++
.
Voyons l'exemple suivant:
int i = 1, j;
j = ++i;
Voici la valeur de j = 2
mais i = 2
. Ici, la valeur de i
sera affectée à j
après l' i
incrémentation de i
. De même ++i
sera exécuté avant j=i;
.
Pour votre question qui devrait être utilisé dans le bloc d'incrémentation d'une boucle for? la réponse est, vous pouvez utiliser n'importe qui .. n'a pas d'importance. Il exécutera votre boucle for no. de fois.
for(i=0; i<5; i++)
printf("%d ",i);
Et
for(i=0; i<5; ++i)
printf("%d ",i);
Les deux boucles produiront la même sortie. ie 0 1 2 3 4
.
Peu importe où vous l'utilisez.
for(i = 0; i<5;)
printf("%d ",++i);
Dans ce cas, la sortie sera 1 2 3 4 5
.
Veuillez ne pas vous soucier de l '"efficacité" (vitesse, vraiment) dont l'une est plus rapide. Nous avons des compilateurs de nos jours qui s'occupent de ces choses. Utilisez celui qui est le plus judicieux à utiliser, en fonction de celui qui montre plus clairement votre intention.
operator++(int)
(la version postfix), le code doit à peu près créer un temporaire qui sera retourné. Êtes-vous sûr que les compilateurs peuvent toujours optimiser cela?
++i
incrémente la valeur, puis la renvoie.
i++
renvoie la valeur, puis l'incrémente.
C'est une subtile différence.
Pour une boucle for, utilisez ++i
, car c'est un peu plus rapide. i++
créera une copie supplémentaire qui sera simplement jetée.
i++
: Dans ce scénario, la valeur est d'abord attribuée, puis l'incrémentation se produit.
++i
: Dans ce scénario, l'incrémentation est d'abord effectuée, puis la valeur est affectée
Ci-dessous est la visualisation de l'image et voici également une belle vidéo pratique qui démontre la même chose.
La raison ++i
peut être légèrement plus rapide que i++
celle qui i++
peut nécessiter une copie locale de la valeur de i avant qu'elle ne soit incrémentée, alors qu'elle ++i
ne le fait jamais. Dans certains cas, certains compilateurs l'optimiseront si possible ... mais ce n'est pas toujours possible, et tous les compilateurs ne le font pas.
J'essaie de ne pas trop compter sur les optimisations des compilateurs, donc je suivrais les conseils de Ryan Fox: quand je peux utiliser les deux, j'utilise ++i
.
i
qu'il n'y en a de la valeur 1 lorsque vous écrivez une instruction 1;
.
Le résultat effectif de l'utilisation de l'une ou l'autre dans une boucle est identique. En d'autres termes, la boucle fera exactement la même chose dans les deux cas.
En termes d'efficacité, il pourrait y avoir une pénalité à choisir i ++ plutôt que ++ i. En termes de spécification de langue, l'utilisation de l'opérateur post-incrémentation devrait créer une copie supplémentaire de la valeur sur laquelle l'opérateur agit. Cela pourrait être une source d'opérations supplémentaires.
Cependant, vous devez considérer deux problèmes principaux avec la logique précédente.
Les compilateurs modernes sont excellents. Tous les bons compilateurs sont suffisamment intelligents pour se rendre compte qu'il voit un incrément entier dans une boucle for, et il optimisera les deux méthodes avec le même code efficace. Si l'utilisation de la post-incrémentation sur la pré-incrémentation entraîne en fait un ralentissement de l'exécution de votre programme, alors vous utilisez un compilateur terrible .
En termes de complexité temporelle opérationnelle, les deux méthodes (même si une copie est en cours de réalisation) sont équivalentes. Le nombre d'instructions exécutées à l'intérieur de la boucle devrait dominer le nombre d'opérations dans l'opération d'incrémentation de manière significative. Par conséquent, dans toute boucle de taille significative, la pénalité de la méthode d'incrémentation sera massivement éclipsée par l'exécution du corps de boucle. En d'autres termes, vous feriez mieux de vous soucier de l'optimisation du code dans la boucle plutôt que de l'incrémentation.
À mon avis, toute la question se résume simplement à une préférence de style. Si vous pensez que la pré-incrémentation est plus lisible, utilisez-la. Personnellement, je préfère le post-incrément, mais c'est probablement parce que c'est ce qu'on m'a appris avant de savoir quoi que ce soit sur l'optimisation.
Il s'agit d'un exemple par excellence d'optimisation prématurée, et des problèmes comme celui-ci ont le potentiel de nous distraire de graves problèmes de conception. Il reste cependant une bonne question à poser, car il n'y a pas d'uniformité dans l'utilisation ou de consensus dans les "meilleures pratiques".
Ils incrémentent tous les deux le nombre. ++i
est équivalent à i = i + 1
.
i++
et ++i
sont très similaires mais pas exactement les mêmes. Les deux incrémentent le nombre, mais ++i
incrémentent le nombre avant que l'expression actuelle ne soit évaluée, tandis quei++
incrémente le nombre après que l'expression est évaluée.
Exemple:
int i = 1;
int x = i++; //x is 1, i is 2
int y = ++i; //y is 3, i is 3
++i
(Opération Prefix): Incrément et affecte alors la valeur
(par exemple): int i = 5
, int b = ++i
Dans ce cas, 6 est associé à b d' abord, puis par incréments à 7 , et ainsi de suite.
i++
(Opération Postfix): cessionnaires et incrémente alors la valeur
(par exemple): int i = 5
,int b = i++
Dans ce cas, 5 est associé à b d' abord, puis par incréments de 6 et ainsi de suite.
Dans le cas d'une boucle for: i++
est principalement utilisé car, normalement, nous utilisons la valeur de départ de i
avant d'incrémenter la boucle for. Mais selon la logique de votre programme, cela peut varier.
Je suppose que vous comprenez maintenant la différence de sémantique (mais honnêtement, je me demande pourquoi les gens posent des questions `` qu'est-ce que l'opérateur X signifie '' sur le débordement de pile plutôt que de lire, vous savez, un livre ou un didacticiel Web ou quelque chose du genre.
Mais quoi qu'il en soit, quant à celui à utiliser, ignorez les questions de performances, qui sont peu importantes, même en C ++. Voici le principe à utiliser pour décider lequel utiliser:
Dites ce que vous voulez dire dans le code.
Si vous n'avez pas besoin de la valeur avant incrément dans votre instruction, n'utilisez pas cette forme d'opérateur. C'est un problème mineur, mais à moins que vous ne travailliez avec un guide de style qui interdit complètement une version en faveur de l'autre (alias un guide de style à tête d'os), vous devez utiliser le formulaire qui exprime le plus exactement ce que vous essayez de faire.
QED, utilisez la version pré-incrémentée:
for (int i = 0; i != X; ++i) ...
La différence peut être comprise par ce simple code C ++ ci-dessous:
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 principale différence est
- Post i ++ ( après incrémentation ) et
++ i Pre ( avant incrément )
- poster si
i =1
la boucle incrémente comme1,2,3,4,n
- pré si
i =1
la boucle incrémente comme2,3,4,5,n
Ce petit code peut aider à visualiser la différence sous un angle différent de celui des réponses déjà publiées:
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);
Le résultat est:
//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
Faites attention aux situations avant et après.
Quant à savoir lequel d'entre eux doit être utilisé dans un bloc d'incrémentation d'une boucle for, je pense que le mieux que nous puissions faire pour prendre une décision est d'utiliser un bon exemple:
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);
Le résultat est:
> iteration #0 > iteration #1 > iteration #2 > iteration #3
> iteration #0 > iteration #1 > iteration #2 > iteration #3
Je ne sais pas pour vous, mais je ne vois aucune différence dans son utilisation, au moins dans une boucle for.
Le fragment de code C suivant illustre la différence entre les opérateurs d'incrémentation et de décrémentation pré et post:
int i;
int j;
Opérateurs d'incrémentation:
i = 1;
j = ++i; // i is now 2, j is also 2
j = i++; // i is now 3, j is 2
Pré-crément signifie incrément sur la même ligne. Post-incrément signifie incrément après l'exécution de la ligne.
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
Lorsqu'il est livré avec les opérateurs OR, AND, cela devient plus intéressant.
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
}
Dans le tableau
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
}
En C ++ post / pré-incrément de variable pointeur
#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)
}
Prochainement:
++i
et i++
fonctionne de la même manière si vous ne les écrivez pas dans une fonction. Si vous utilisez quelque chose comme function(i++)
ou function(++i)
vous pouvez voir la différence.
function(++i)
dit le premier incrément i de 1, après cela, mettez-le i
dans la fonction avec une nouvelle valeur.
function(i++)
dit mettre d'abord i
dans la fonction après cet incrément i
de 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;
et int k = i++;
même quand aucun appel de fonction n'est impliqué.
La seule différence est l'ordre des opérations entre l'incrément de la variable et la valeur retournée par l'opérateur.
Ce code et sa sortie expliquent la différence:
#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);
}
La sortie est:
i before: 1; value returned by i++: 0, i after: 1
i before: 1; value returned by ++i: 1, i after: 1
Donc, ++i
retourne essentiellement la valeur après son incrémentation, tout en ++i
retournant la valeur avant son incrémentation. À la fin, dans les deux cas, la i
valeur sera incrémentée.
Un autre exemple:
#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;
}
Production:
i=0, i++*2=0
i=0, ++i*2=2
i=0, (++i)*2=2
i=0, (++i)*2=2
Les différences sont claires lorsque la valeur retournée est affectée à une autre variable ou lorsque l'incrément est effectué en concaténation avec d' autres opérations où la priorité des opérations est appliquée ( i++*2
est différent ++i*2
, mais (i++)*2
et (++i)*2
retourne la même valeur) dans de nombreux cas , ils sont interchangeables. Un exemple classique est la syntaxe de boucle for:
for(int i=0; i<10; i++)
a le même effet de
for(int i=0; i<10; ++i)
Pour ne faire aucune confusion entre les deux opérateurs j'ai adopté cette règle:
Associer la position de l'opérateur ++
par rapport à la variable i
à l'ordre de l' ++
opération par rapport à l'affectation
Autrement dit:
++
avant i
signifie que l'incrémentation doit être effectuée avant l' affectation;++
après l' i
incrémentation doit être effectuée après l' affectation:Vous pouvez considérer la conversion interne de cela comme plusieurs déclarations ;
i++;
vous pouvez le penser comme,
i;
i = i+1;
++i;
vous pouvez le penser comme,
i = i+i;
i;
a = i ++ signifie a contient la valeur i actuelle a = ++ i signifie a contient la valeur i incrémentée
a = i++;
signifie que la valeur stockée dans a
sera la valeur d' i
avant l'incrémentation, mais "sans incrémentation" implique qu'elle i
n'est pas incrémentée, ce qui est complètement faux -i
est incrémenté, mais la valeur de l'expression est la valeur avant l'incrémentation.
Voici l'exemple pour comprendre la différence
int i=10;
printf("%d %d",i++,++i);
sortie: 10 12/11 11
(selon l'ordre d'évaluation des arguments de la printf
fonction, qui varie selon les compilateurs et les architectures)
Explication:
i++
->i
est imprimé, puis incrémente. (Imprime 10, mais i
deviendra 11)
++i
-> la i
valeur augmente et imprime la valeur. (Imprime 12, et la valeur de i
également 12)
i++
et++i