La sortie de ce code C est 49 mais quelqu'un peut-il m'expliquer comment? [dupliquer]
#include <stdio.h>
#define CUBE(x) (x * x * x)
int main() {
printf("%d", CUBE(4+5));
return 0;
}
Réponses
Macro transformera le code en:
printf("%d", (4+5 * 4+5 * 4+5));
ce qui est effectivement:
printf("%d", 4 + (5*4) + (5*4) + 5); // 29
Si vous voulez 9
obtenir un cube 729
, vous devez écrire CUBE((4+5))
.
Voici comment la macro est développée pendant le processus de compilation:
printf("%d", (4+5 * 4+5 * 4+5));
Parce que *
a une priorité plus élevée que +
, cette expression est évaluée comme (4 + (5 * 4) + (5 * 4) + 5)
, produisant 49
au lieu de l'attendu 729
.
Pour éviter de tels problèmes de priorité des opérateurs, tous les arguments de macro doivent être mis entre parenthèses dans la définition de macro ainsi que dans l'expression elle-même:
#define CUBE(x) ((x) * (x) * (x))
Notez cependant que cette expansion de CUBE
évalue x
plusieurs fois, ce qui pose un problème si l'argument macro a des effets secondaires, tels que CUBE(i++)
.
Pour éviter tous ces problèmes, utilisez une fonction et laissez le compilateur l'optimiser:
int cube(int x) {
return x * x * x;
}
Vous pouvez ajouter static inline
avant cette définition de fonction, mais les optimiseurs modernes incorporeront toujours la fonction sans cela.
Le préprocesseur C substituera littéralement toutes les instances de x par 4 + 5, ce qui donnera le code suivant:
i = 4+5*4+5*4+5;
(multiplication d'abord, puis addition)
vous devez donner l'entrée comme CUBE((4+5))
si vous voulez ajouter les nombres, puis envoyer à CUBE
. Parce que cela CUBE(4+5)
est essentiellement étendu à 4+5*4+5*4+5
car il place le tout 4+5
à la place de x
. Donc, 4+5*4+5*4+5
= 4+20+20+5
comme la multiplication vient en premier, puis les ajouter donnera 49
.
Définissez la macro comme si #define CUBE(x) ((x)*(x)*(x))
elle procédait d'abord à l' (4+5)
opération pour chaque (x)
, puis effectuez l' *
opération.
Une autre façon consiste simplement à utiliser CUBE((4+5))
lors de l'appel de la macro, en gros, il a d'abord ajouté les deux nombres et (4+5)
= 9
puis faites CUBE(9)
, comme:
#include<stdio.h>
#define CUBE(x) (x * x * x)
int main( )
{
printf("%d", CUBE((4+5)));
return 0;
}
Lisez Modern C , puis le projet de norme C n1570 , et la documentation de GCC et de GDB et de CPP . Voir également ce site Web de référence C.
Inspirez-vous des projets open source existants, par exemple sur github ou sur des logiciels GNU .
Avec un compilateur GCC récent , invoquez-le comme gcc -Wall -Wextra -g
. Utilisez également les -C -E
options pour obtenir le formulaire prétraité.
Vous pourriez également être intéressé par l' extension statement-expr de GCC.
Votre CUBE(4+5)
est macro-expansion à 4+5*4+5*4+5
laquelle est calculée comme 4+(5*4)+(5*4)+5
fonction de la priorité des opérateurs C .
Pensez à coder une static inline
fonction comme
static inline int cube(int x) { return x*x*x; }
ou si vous avez besoin d'une macro, au moins
#define CUBE(X) ((X)*(X)*(X))
ce qui ne fonctionnera pas bien pour CUBE(i++)
(alors qu'avec la inline
fonction, cube(i++)
fait ce que vous voulez qu'elle fasse: incrémenter i
une fois!).
BTW, vous pouvez utiliser GPP , ou GNU m4 , (ou votre propre générateur, ou GNU bison ) pour générer du code C. En règle générale, pensez avec les AST : lorsque vous générez du code C, émettez beaucoup de parenthèses inutiles, comme par exemple dans Chicken Scheme , SWIG , ou dans CAIA ou dans mon manydl.c
Vous pouvez également utiliser l' analyseur statique Clang sur votre code (et peut - être Frama-C ).
Vous pourriez être intéressé par la lecture de quelques directives de codage comme celles de MISRA C ou GNU .