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?
c
for-loop
post-increment
pre-increment
The.Anti.9
la source
la source
Réponses:
++i
incrémentera la valeur dei
, puis renverra la valeur incrémentée.i++
incrémentera la valeur dei
, mais renverra la valeur d'origine quii
contenait avant d'être incrémentée.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ôti++
" et vous ne vous tromperez pas.Il y a quelques commentaires concernant l'efficacité de
++i
eti++
. 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.la source
for(int i=0; i<10; i++){ print i; }
cela ne sera-t-il pas différent defor(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++
etprint i
sont dans des déclarations différentes, mais parce quei++;
eti<10
sont. La remarque de @ jonnyflash n'est pas que hors de la base. Supposons que vous ayezfor(int i=0; i++<10){ print i; }
etfor(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émentei
la valeur de 1 après la fin de l'opération.Voyons l'exemple suivant:
Voici la valeur de
j = 1
maisi = 2
. Ici, la valeur dei
sera affectée àj
first puisi
sera incrémentée.++i
++i
est pré-incrémenté car il incrémentei
la valeur de 1 avant l'opération. Cela signifiej = i;
s'exécutera aprèsi++
.Voyons l'exemple suivant:
Voici la valeur de
j = 2
maisi = 2
. Ici, la valeur dei
sera affectée àj
après l'i
incrémentation dei
. De même++i
sera exécuté avantj=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.
Et
Les deux boucles produiront la même sortie. ie
0 1 2 3 4
.Peu importe où vous l'utilisez.
Dans ce cas, la sortie sera
1 2 3 4 5
.la source
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.
la source
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.la source
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éeCi-dessous est la visualisation de l'image et voici également une belle vidéo pratique qui démontre la même chose.
la source
La raison
++i
peut être légèrement plus rapide quei++
celle quii++
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
.la source
i
qu'il n'y en a de la valeur 1 lorsque vous écrivez une instruction1;
.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".
la source
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:
la source
++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 dei
avant d'incrémenter la boucle for. Mais selon la logique de votre programme, cela peut varier.la source
++i
: est pré-incrémenté, l'autre est post-incrémenté.i++
: récupère l'élément puis l'incrémente.++i
: incrémente i puis renvoie l'élément.Exemple:
Production:
la source
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:
la source
La différence peut être comprise par ce simple code C ++ ci-dessous:
la source
la source
i ++ et ++ i
Ce petit code peut aider à visualiser la différence sous un angle différent de celui des réponses déjà publiées:
Le résultat est:
Faites attention aux situations avant et après.
pour boucle
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:
Le résultat est:
Je ne sais pas pour vous, mais je ne vois aucune différence dans son utilisation, au moins dans une boucle for.
la source
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:
Opérateurs d'incrémentation:
la source
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.
Lorsqu'il est livré avec les opérateurs OR, AND, cela devient plus intéressant.
Dans le tableau
En C ++ post / pré-incrément de variable pointeur
la source
Prochainement:
++i
eti++
fonctionne de la même manière si vous ne les écrivez pas dans une fonction. Si vous utilisez quelque chose commefunction(i++)
oufunction(++i)
vous pouvez voir la différence.function(++i)
dit le premier incrément i de 1, après cela, mettez-lei
dans la fonction avec une nouvelle valeur.function(i++)
dit mettre d'abordi
dans la fonction après cet incrémenti
de 1.la source
int j = ++i;
etint 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:
La sortie est:
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, lai
valeur sera incrémentée.Un autre exemple:
Production:
Plusieurs fois, il n'y a pas de différence
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:a le même effet de
Règle à retenir
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 variablei
à l'ordre de l'++
opération par rapport à l'affectationAutrement dit:
++
avanti
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:la source
Vous pouvez considérer la conversion interne de cela comme plusieurs déclarations ;
vous pouvez le penser comme,
vous pouvez le penser comme,
la source
a = i ++ signifie a contient la valeur i actuelle a = ++ i signifie a contient la valeur i incrémentée
la source
a = i++;
signifie que la valeur stockée dansa
sera la valeur d'i
avant l'incrémentation, mais "sans incrémentation" implique qu'ellei
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
sortie:
10 12/11 11
(selon l'ordre d'évaluation des arguments de laprintf
fonction, qui varie selon les compilateurs et les architectures)Explication:
i++
->i
est imprimé, puis incrémente. (Imprime 10, maisi
deviendra 11)++i
-> lai
valeur augmente et imprime la valeur. (Imprime 12, et la valeur dei
également 12)la source
i++
et++i