6
votes

L'utilisation de macro entraîne une sortie incorrecte lorsqu'il est utilisé dans le cadre d'une expression mathématique plus grande - pourquoi cela se produit-il?

Il s'agit d'un programme de routine C normal que j'ai découvert dans une banque de questions. Il est indiqué ci-dessous:

#define CUBE(p) p*p*p

main()
{
    int k;
    k = 27 / CUBE(3);
    printf("%d", k);
}


5 commentaires

Il suffit de remplacer cube (3) dans votre k = ... ligne par 3 * 3 * 3 et voyez ce que vous obtenez votre expression .


Quelle langue est-ce que «des doutes» semble être un synonyme de "problème" ou "question"?


@ETher: comme un Indien, je peux définitivement dire que c'est nous. J'ai appris le difficile chemin moi-même! Une fois que mon professeur m'a dit: "Avez-vous un doute sur la question, ou une question sur la question?" J'espère que vous ne doutez pas de moi quand je dis ça. :-)


Lorsque vous travaillez avec un problème de préprocesseur, comme celui-ci, utilisez la sortie de préprocesseur pour voir où se trouve le problème (GCC -E File.c)


C'est pourquoi il est recommandé d'utiliser des fonctions au lieu de macros. Sur la plupart des compilateurs modernes, la vitesse est la même.


13 Réponses :


15
votes

Le préprocesseur se substitue simplement xxx

avec xxx

afin de vous retrouver avec: xxx

Qui, évalué de gauche à droite avec la priorité de l'opérateur, est en fait 81.

Si vous ajoutez des parenthéses autour de la macro, vous devez trouver les résultats sont corrects: < Pré> xxx

Il serait encore préférable d'entourer chaque instance de p avec des parenthéses aussi, comme dans: xxx

Qui vous permettra de passer des expressions à la macro correctement (par exemple, 1 + 2 ).


4 commentaires

Ou, meilleur, #define cube (p) (p) * (p) * (p))


Je le ferais effectivement: #define cube (p) (p) * (p) * (p) * (p)) mais même c'est mauvais, si p est un appel de fonction. Cela peut être appelé par inadvertance 3 fois.


wow ... c'est juste le jeu de la précédente de l'opérateur.Merci James et Alok.


C'est pourquoi la Convention est d'utiliser des majuscules pour les macros - afin que vous réalisiez qu'ils peuvent évaluer leurs arguments plus d'une fois.



0
votes
k= 27/3*3*3 

 =(((27/3)*3)*3) (The precedence of `*` and `/` are same but the associativity is from left to right)
 =((9*3)*3) =81

0 commentaires

3
votes

Les préprocesseurs doivent être parenthèses correctement. Remplacez-le par

#define CUBE(p) ((p)*(p)*(p))


1 commentaires

Et méfiez-vous, même ceci est cassé pour Cube (++ I) ou Cube (F (x))



1
votes

Votre macro n'est pas protégée. Essayez xxx

la macro actuelle a été étendue à xxx

qui est ((27/3) * 3) * 3


0 commentaires

0
votes
#define CUBE(p) ((p)*(p)*(p))

0 commentaires

0
votes

Lorsque vous faites des macros, vous devez faire attention à la façon dont vous placez des parenthèses. Dans ce cas, vous n'en avez pas, l'expression devient donc 27/3 * 3 * 3, qui par la présence des règles de / et * devient (27/3) * 3 * 3.


0 commentaires

2
votes

C macros de la substitution textuelle (c'est-à-dire que c'est équivalent à la copie et au code de collage). Donc, votre code va de: xxx

à xxx

division et multiplication ont la même précision et avoir une associativité à droite à droite, donc Ceci est analysé comme suit: xxx

9 * 3 * 3 = 81.

C'est pourquoi les macros C devraient toujours être définis avec une utilisation libérale de Parenthèses: xxx

Pour plus d'informations, reportez-vous à la section http://c-faq.com/cpp/safemacros.html à partir de la FAQ comp.lang.c.


0 commentaires

2
votes

Étant donné que les macros sont une substitution textuelle qui fonctionne à: xxx

puisque la multiplication et la division se produisent de gauche à droite, cela fonctionne à: xxx

Donc, vous voulez modifier cela de deux manières: xxx

Les parenthèses extérieures font que les multiplications soient effectuées avant toute autre opération. < p> Les parenthèses autour des PP sont pour le cas où vous faites: xxx

sans ces parenthèses intérieures, la priorité de l'opérateur vous trébuchera.


0 commentaires

0
votes

27/3 * 3 * 3 = 9 * 3 * 3 = 81?


0 commentaires

0
votes

Les deux / et * les opérateurs ont la même précalence. Pour exécuter 3 * 3 * 3 d'abord, vous devriez les enfermer entre parenthèses.

#include <stdio.h>

#define CUBE(p) p*p*p

int
main ()
{
  int k;
  k=27/(CUBE(3));
  printf("%d",k);
  return 0;
}


0 commentaires

4
votes

à cause de la précédente opérateur 27/3 * 3 * 3 = 81 code> strong>

Vous pouvez utiliser à la place: p>

inline int cube(int p) { return p*p*p; }


0 commentaires

0
votes

C'est la manière dont l'associativité et la priorité des opérateurs sont mises en œuvre. Quand l'expression est élargie, il devient 27/3 * 3 * 3 et non 27 / (3 * 3 * 3) Maintenant, la division et la multiplication ont la même précalence en C mais l'associativité est laissée à droite pour les deux. Donc, il peut être montré comme suit: (27/3) * 3 * 3 qui à son tour est égal à (9 * 3) * 3 = 81 De plus, si vous vous souvenez de l'ancienne règle arithmétique de Bodmas (SUPPLICATION DE SUPPORT DE DIVISION DE DIVISION) , c'est l'ordre de la priorité, nous faisons ensuite la division d'abord, puis la multiplication. Encore une fois, nous obtenons une réponse comme 81 pour 27/3 * 3 * 3.


0 commentaires

0
votes

HI réponse pour cela est: 81 Explication: À l'étape k = 27 / cube (3) Cube (3) est remplacé par 3 * 3 * 3 par préprocesseur.Then ci-dessus déclaration devient as k = 27/3 * 3 * 3 Dans cette expression 27/3 est évaluée par C compilateur C (précédence de l'opérateur) Le résultat est (27/3): 9 La déclaration K = 27/3 * 3 * 3 devient comme k = 9 * 3 * 3; Le résultat de la déclaration ci-dessus est de 81:


0 commentaires