Pourquoi les deux sorties sont différentes?

J’ai utilisé le code C suivant et il a donné la sortie comme d’habitude:

9, 25

#include int PRODUCT(int x) { return (x*x); } void main() { int i = 3, j, k; j = PRODUCT(i++); k = PRODUCT(++i); printf("%d, %d\n", j,k); } 

Cependant, quand j’utilisais la définition de la macro au lieu de la fonction suivante:

 #include #define PRODUCT(x) (x*x) void main() { int i = 3, j, k; j = PRODUCT(i++); k = PRODUCT(++i); printf("%d, %d\n", j,k); } 

la sortie était

9, 49

J’ai essayé de visualiser le code de compilation en utilisant cpp filename.c et l’extension de main ressemblait à ceci:

 void main() { int i = 3, j, k; j = (i++*i++); k = (++i*++i); printf("%d, %d\n", j,k); } 

Je ne comprends pas pourquoi l’opération d’incrémentation est effectuée deux fois avec des macros. J’apprends le C seul et je n’arrive pas à comprendre pourquoi. Merci d’avance pour votre aide!

Les macros réécrivent littéralement votre programme source avant la compilation. Comme vous le montrez, votre code est:

 j = (i++*i++); k = (++i*++i); 

Voir le double ++ dans chaque ligne? Cela augmente i deux fois à chaque fois. Avec les fonctions, l’argument est évalué une fois, donc il incrémente i une fois à chaque fois.

En substitution de macro, l’utilisation de la macro est littéralement remplacée par le contenu de la macro avant la compilation.

Je voudrais donner un exemple différent de la façon dont cela peut tourner terriblement mal s’il n’est pas utilisé correctement. Espérons que cela montre aussi ce que moi (et d’autres réponses) entendions par « littéralement remplacé»

Tu as écrit:

 #define PRODUCT(x) (x*x) 

Si tu fais:

 PRODUCT(a + b) 

Cela devient, après substitution:

 (a + b*a + b) 

Ce qui n’est pas la même chose que:

 (a+b) * (a+b) 

L’incrémentation est effectuée deux fois parce qu’une macro est plus ou moins une substitution textuelle, comme vous l’avez découvert. Ainsi, tout argument de macro utilisé plusieurs fois sera évalué plusieurs fois.

Cette réponse SO a quelques astuces qui peuvent aider à éviter ce problème.

La réponse est juste là dans votre dernier exemple.

 void main() { int i = 3, j, k; j = (i++*i++); k = (++i*++i); printf("%d, %d\n", j,k); } 

Vois-le de cette façon:

 i = 3, i = 3 3 x 3 = 9 i++ = 4 i++ = 5 ++i = 6 ++i = 7 7 x 7 = 49. 

Après avoir évalué i ++ ou ++ i , la nouvelle valeur de i sera la même dans les deux cas . La différence entre pré-incrément et post-incrément réside dans le résultat de l’évaluation dans l’expression.

i ++ évalue l’ancienne valeur de i et incrémente i.

++ i incrémente i et évalue la nouvelle valeur de i.

Dans votre code,

j = (i ++ * i ++);

L’expression évalue l’ ancienne valeur de i (c’est-à-dire) 3 et le 1er i ++ incrémente i à 4 et le second i ++ incrémente i à 5

Votre première déclaration est évaluée à

j = 3 * 3;

La valeur j résultante est 9.

Après cette déclaration, la valeur de i est 5 .

Ensuite,

k = (++ i * ++ i);

1st ++ i incrémente i à 6 et 2nd i ++ incrémente i à 7 et l’expression évalue la nouvelle valeur de i (ie) 7.

Votre deuxième déclaration est évaluée à

k = 7 * 7;

La valeur k résultante est 49 .

Référez-vous à ce lien: http://en.wikipedia.org/wiki/Increment_and_decrement_operators

Cela se produit car, lorsque le préprocesseur effectue le développement de macros, vous pouvez le considérer comme s’il remplaçait du texte avant la compilation. Chaque fois qu’il voit x , il le remplace par ce que vous y mettez. Donc x -> i++ ou ++i . C’est pourquoi les augmentations se produisent deux fois chacune.