Pourquoi n++ exécuter plus rapidement que n=n+1?
En langage C, Pourquoi ne n++
l'exécution est plus rapide que n=n+1
?
(int n=...; n++;)
(int n=...; n=n+1;)
Notre instructeur posé cette question dans la séance d'aujourd'hui. (ce n'est pas de devoirs)
- Ce qui est
n
? ___ - Comment avez-vous trouvé ça? Sur le compilateur/OS/plate-forme/architecture?
- Ce n'est pas, en général. Vous ne pouvez pas faire une déclaration significative que "
a
est plus rapide queb
" (oùa
etb
C sont des expressions). Il n'a de sens que de dire que "a
est plus rapide queb
sur le matérielc
lorsqu'il est compilé avec la versiond
de compilateure
avec des options d'optimisationf
" (et quelques autres exigences). - C'est clairement ce qui est demandé ici de l'exemple; tout simplement parce que la réponse semble évidente ne signifie pas que vous devriez la fermer. +1 pour les rouvrir.
- Oui, je pense qu'il doit être rouvert..
- Ce n'est pas une vraie question, car il se demande pourquoi un sens l'énoncé est vrai. Il pourrait aussi bien demander: "Pourquoi avez-green ideas sleep furiously?".
- Canon: Au moins, il est vrai, parfois, dans le passé..
- Donc l'interlocuteur devrait être corrigé dans la réponse. C'est toujours une bonne question, parce que quelqu'un d'autre peut venir à travers la même désinformation plus tard, et cette question sera d'aider à les trier
- aussi, si vous vous sentez vraiment que la question ne devrait pas poser une fausse déclaration, n'hésitez pas à modifier pour qu'il "Est
n++
plus vite quen = n + 1
, et pourquoi?". C'est beaucoup plus constructif que de simplement fermer sans discussion 🙂 - double possible de (C) Quelle est la différence entre ++i et i++
- À moins que vous fournir un certain type de contexte, s'il vous plaît arrêter de rouler des modifications que le lien à des questions qui sont clairement liés à ce que vous demandez.
- Et pour cette question, s'il vous plaît arrêter de revenir tente d'en faire une plus claire et pédagogique de la question; à moins d'y ajouter un commentaire si vous êtes en désaccord avec les modifications.
- Je ne pense pas que cela devrait être dans le wiki de la communauté..
- Trop tard. DONC convertit automatiquement une question à la Communauté Wiki si 5 personnes ou plus modifier une question.
- Vote pour le rouvrir. Je ne vois pas comment ce n'est pas une vraie question. Tout simplement parce que l'OP a un mauvais enseignant, ne signifie pas que la question n'est pas légitime.
n++;
etn=n+1;
sera presque certainement compiler le même code machine sur n'importe quel compilateur moderne. Sur les premiers compilateurs C ce n'était pas le cas et que le compilateur serait seulement de réaliser qu'il pouvait utiliser le processeur cible de l'incrément de l'enseignement si vous lui avez ditn++
. Sinon, il pourrait ne plus générale, à ajouter de l'instruction qui aurait été une plus grande instruction ou ont été deux instructions. Si votre instructeur vraiment vous a dit qu'il était plus rapide et n'était pas en parler en étant plus rapide pour vous de type "n++" que "n=n+1", puis il est mauvais. Essayezgcc -S prog.c;less prog.s
- Il a été fermé, puis on les fixe dans une vraie question et rouvert, alors que l'OP est revenue et la question a été de nouveau fermé. Franchement, si l'OP va tirer ce genre de comportement, alors à mon humble avis il doit rester fermé.
- Je crois que ce n'est pas une vraie question, car elle postule une fausse situation, et n'a pas de réponse. "Pourquoi les zèbres sont plus grandes que les éléphants?"
- WTF pourquoi quelqu'un a mis une prime sur un wiki de la communauté avec l'accepté de répondre et de façon flagrante les prémisses fausses?!
- La vraie question est: Pourquoi votre université permettre à un incompétent professeur pour enseigner?
- Pour répondre à ma propre question: le fait d'avoir un bounty fait une question unclosable. Donc, apparemment, gcc mettre le bounty sur elle pour nous empêcher de le fermer.
- Hey, je suis d'accord que ++n est plus optimisé que le n++. Mais n=n+1? LOL!
- Soit vous vous moquez ou que vous avez raté que cette question est étiqueté C et pas du C++....
- Je ne sais pas à propos de l'exécution, mais la compilation peut prendre en plaisantant petite quantité de moins de temps, puisque
n=n+1;
faudrait 2 octets de plus quen++;
pour entrer dans la mémoire. Encore une fois cette hypothèse est peut-être vrai que pour certains pré-âge de pierre, ère, que nous avons maintenant de bloquer les lectures et les écritures et les choses... - Cette même question est sur la NASCAR blog "Mon frère de l'ami de l'oncle dit que sa voiture est plus rapide si c'est le numéro 01 de 10".
- Wow je peux donner 5 +1? Vous avez failli m'a fait cracher mon café en riant.
- double possible de quelle est la différence en termes d'efficacité de l'aide i++/++i/i+=1/i=i+1 si aucun optimisation du compilateur est utilisé
Vous devez vous connecter pour publier un commentaire.
Ce serait vrai si vous travaillez sur un "âge de pierre" compilateur...
En cas de "âge de pierre":
++n
est plus rapide quen++
est plus rapide quen=n+1
Machine ont généralement
increment x
ainsi queadd const to x
n++
, vous aurez 2 accès mémoire seulement (lire n, inc n, écrire n )n=n+1
, vous avez 3 accès à la mémoire (lecture n, const lire, ajouter n et const, écrire n)Mais aujourd'hui, le compilateur va automatiquement convertir
n=n+1
à++n
, et cela ne sera plus que vous pouvez imaginer!!Également aujourd'hui de processeurs -malgré le cas de "âge de pierre" compilateur d'exécution ne peuvent pas être affectées à tous les dans de nombreux cas!!
Liées
n=n+1
àn++
; elle ferait de l'ensemble de la charge, d'exploiter, de stocker des affaires comme si1
une valeur constante.++n
etn++
était exactement à la même vitesse, il n'est pas à charge de l'incrément magasin, et la seule différence de vitesse que vous voyez dépend de lan
a été stocké dans un registre ou mémoire (pas que n qui est arrivé à être dans un registre dès maintenant, mais si oui ou non ses de stockage alloué était dans un registre), par exemplemove (n)+,r0
se déplace n pour inscrire zéro, l'incrémentation de n après le déménagement. (VAX-11 de l'assemblée)n=n+1
à++n
" est tout simplement fausse, ou même non-sens. C'est comme dire un traducteur "convertirit is
àit's
" lors de la traduction de l'anglais vers le français. La distinction entre les deux est un artefact de la langue source.++n
peut être plus rapide quen++
car elle ne nécessite pas la précédente valeur de n doit être copiée, enregistrée au cours de l'incrément, et s'en retourna."?++
opérateur "d'un grand et cher-pour-copie de type de données". Mais même si il n'y avait, pas de copie est en cause. L'incrémentation se passe en tout temps après l'opérateur de post-incrémentation, mais avant que la prochaine fois que la valeur est utilisée, longtemps après la valeur qui a été utilisée dans l'expression actuelle.++
pouvez seulement être appliquée aux types numériques en C donc il n'y a jamais besoin de copier quoi que ce soit.n=n+0
au lieu den=n+1
?Sur GCC 4.4.3 pour les architectures x86, avec ou sans optimisations, ils compiler le même code assembleur, et ainsi prendre la même quantité de temps à s'exécuter. Comme vous pouvez le voir dans l'assemblée, GCC, convertir
n++
enn=n+1
, puis il optimise l'une instruction add (dans l'-O2).Votre instructeur de la suggestion que
n++
est plus rapide ne s'applique qu'à de très anciens, non-optimisation des compilateurs, qui n'ont pas été assez intelligent pour sélectionner la mise à jour des instructions pourn = n + 1
. Ces compilateurs sont obsolètes dans le monde PC depuis des années, mais peut encore être trouvé pour bizarre propriétaire plateformes embarquées.Code C:
Assembly de sortie (pas d'optimisations):
Assembly de sortie (avec -O2 optimisations):
-O0
mais cela ne fonctionne toujours présent...Le compilateur d'optimiser
n + 1
dans le néant.Voulez-vous dire
n = n + 1
?Dans ce cas, de compiler à l'identique de l'assemblée. (En supposant que les optimisations sont et qu'ils sont des états, pas des expressions)
Qui dit qu'il fait? Votre compilateur optimise tout de suite, vraiment, en faisant un point discutable.
Les compilateurs modernes doivent être capables de reconnaître les deux formes équivalentes et de les convertir vers le format qui fonctionne le mieux sur votre plate-forme cible. Il existe une exception à cette règle: la variable d'accès qui ont des effets secondaires. Par exemple, si
n
est de la mémoire mappée matériel de registre, de lecture et d'écriture peuvent faire plus que simplement le transfert d'une valeur de données (lecture claire une interruption, par exemple). Vous devez utiliser lavolatile
mot-clé pour permettre au compilateur de savoir qu'il faut être prudent sur l'optimisation de l'accès àn
, et dans ce cas, le compilateur peut générer du code à partir den++
(opération d'incrémentation) etn = n + 1
(lire, ajouter, et les opérations de banque). Toutefois, pour les variables normales, le compilateur doit optimiser les deux formes de la même chose.volatile
n'entraîne pas de différence entre++n
etn=n+1
. La fois le résultat en une seule lecture et une écriture unique, et ni est atomique. Si vous voulez atomicité,volatile
ne peut pas les lui fournir; attendre_Atomic
types de C1x.Il n'a pas vraiment. Le compilateur va apporter des modifications spécifiques à l'architecture cible. Micro-optimisations comme cela a souvent douteux avantages, mais, surtout, sont certainement pas la peine de le programmeur du temps.
En fait, la raison est que l'opérateur est défini différemment pour le post-fix qu'il est pour le pré-fix.
++n
incrémenter "n" et de renvoyer une référence à "n" alors quen++
incrémenter "n" retour d'unconst
copie de "n". Par conséquent, le membre de phrasen = n + 1
sera plus efficace. Mais je suis d'accord avec les affiches ci-dessus. Bon les compilateurs doivent optimiser loin d'un retour non utilisé objet.En langage C les effets secondaires de
n++
expressions est par définition équivalent à l'effet secondaire den = n + 1
expression. Depuis votre code s'appuie sur les effets secondaires, il est immédiatement évident que la réponse correcte est que cette expression n'ont toujours exactement les mêmes performances. (Peu importe les paramètres d'optimisation du compilateur, BTW, puisque la question n'a absolument rien à voir avec toutes les optimisations.)Un écart de rendement de ces expressions n'est possible que si le compilateur est intentionnellement (et malicieusement!) essaie d'introduire de la divergence. Mais dans ce cas, il peut aller de toute façon, bien sûr, c'est à dire selon la manière dont le compilateur de l'auteur a voulu biaiser il.
+
devrait être mis en œuvre qu'à AJOUTER et que++
devrait être mis en œuvre par INC.%
n'est pas spécifiée, afin de savoir si votre matériel vous donne un unsigned modulo ou potentiellement signé reste comme une instruction machine, vous pouvez toujours la carte de l'opérateur assez simple instruction machine.++
variante et+ 1
variante, qui est l'ensemble de point. La raison pour laquelle la norme a tellement de trucs à gauche indéfini est de donner au compilateur de plus de liberté dans l'optimisation du code. Ironiquement, dans la plupart des cas (y compris celui-ci) c'est en fait l'opposé de la primitive approche de traduction lors de la C des opérations sont juste carrément mappé à l'exploitation des machines.x++; y++;
de telle manière que l'on utiliseINC
, l'autre utiliseADD 1
. L'enfer, il peut utiliserSUB -1
si il voulait vraiment. Le point est, même pour littéralement identiques code C, le code généré peut différer d'instance en instance. Seulement la sémantique de la matière en fin de compte. Je voudrais quelqu'un pour mettre en œuvre un -O-1 option de GCC un de ces jours deoptimize code 😀Je pense que c'est plus une question de matériel plutôt que logiciel... Si je me souviens corectly, dans les Processeurs plus anciens n=n+1 nécessite deux emplacements de mémoire, où l' ++n est tout simplement un microcontrôleur commande... Mais je doute que cela s'applique pour les architectures modernes...
Toutes ces choses dépend du compilateur/processeur/directives de compilation. Donc, faire toutes les hypothèses "ce qui est plus rapide en général" n'est pas une bonne idée.