9
votes

C Préprocesseurs et ordre des opérations

J'apprends C, mais je ne comprends pas ceci:

#define square(x) x*x
a = square(2+3) //a = 11


4 commentaires

Juste comme un conseil, cet exemple montre l'une des nombreuses raisons pour lesquelles vous devriez éviter d'utiliser des macros en C jusqu'au jour où vous êtes là où vous Vraiment Sachez ce que vous faites. Bien sûr, quand ce jour-là vient, vous saurez pourquoi les éviter en détail ...


@ T.E.D.: Macros (et le préprocesseur en général) sont un outil comme n'importe quel autre. Cet exemple ne montre pas pourquoi vous ne devez pas utiliser de macros en général - il montre simplement une affaire d'utilisation particulière pour laquelle il est inapproprié de les appliquer. Il y a à la fois de bonnes et de mauvaises utilisations des macros.


Cela dit, il y a bien sûr plus de mauvaises utilisations que de bonnes :)


Nommez mieux la question de la question


5 Réponses :


23
votes

Il se développe à 2 + 3 * 2 + 3 , ce qui est équivalent à 2+ (3 * 2) +3 . Utilisez des parenthèses pour le réparer: xxx

essayez maintenant avec carré (x ++) et vous rencontrerez plus de problèmes (comportement non défini). Évitez de faire cela comme une macro si vous le pouvez.


2 commentaires

La fonction équivalente C ++ doit être aussi efficace qu'une macro (sur des compilateurs modernes avec des optimisations devenant) et ne souffrira pas de ce problème.


@Martin: Correct, si l'op utilise c ++. Les indications sont-elles probablement C. Je pense que C99 a également des fonctions en ligne, et il apparaît qu'ils sont une extension de GNU C. EN.Wikipedia.org/wiki/Inline_function#Language_support



12
votes

carré (2 + 3) code> se développe à 2 + 3 * 2 + 3 code> équivalent à 2+ (3 * 2) +3 code> [ * code> a une priorité supérieure à celle + code>]

sur gcc, vous pouvez utiliser l'option --e code> pour voir ce que votre prétraiteur génère p> xxx pré>

remède p>

ESSAYEZ CE P>

#define square(x) ((x)*(x))


1 commentaires

+1 Pour non seulement trouver le problème, mais également enseigner l'OP (et le reste de nous) Comment déboguer de tels problèmes.



1
votes

car 2 + 3 est substitué littéralement dans l'expression x * x , il devient 2 + 3 * 2 + 3 , et le * L'opérateur a une priorité plus élevée afin que vous n'obtiens pas au résultat attendu.

toujours enterrer des arguments macro et toute l'expression entre parenthèses pour éviter ceci: xxx

Notez également que toute expression que vous passez sera évaluée deux fois, ce qui peut être indésirable si l'expression a un effet secondaire tel qu'une affectation ou un appel de fonction. Dans ces cas, il est préférable d'utiliser une fonction en ligne.


2 commentaires

Toujours enterrer des macros entre parenthèses aussi. Avec votre suggestion, 1.0 / carré (x) serait alors évalué à 1.0 / (2 + 3) * (2 + 3) , donc 1.0 au lieu de 0,04 .


@Sam: Point pris. Ironique, mais j'ai moi-même dit que quelques mois il y a quelques mois dans cette réponse: Stackoverflow.com/Questions/4455307/...



1
votes

Essayez:

#define square(x) ((x)*(x))


0 commentaires

0
votes

Pensez à ce que vous obtenez lorsque la macro est élargie. Le préprocesseur C étendra ceci comme xxx pré>

vous devez définir correctement votre macro. Encourrez toujours la variable macro entre parenthèses. Cela vous donnerait le résultat attendu. P>

a = ((2 + 3) * (2 + 3))


2 commentaires

Votre conseil n'est pas «définissant correctement» la macro. 1.0 / carré (x) serait évalué à 1.0 / (2 + 3) * (2 + 3) , donc 1.0 au lieu de < Code> 0.04 .


J'ai corrigé la macro mal définie. A ajouté un autre ensemble de parenthèses entourant.