Macro functions
- Renaud Jordi
- 22 nov. 2024
- 2 min de lecture
#define PRODUCT(a, b) (a*b)
int p = PRODUCT(3,5);
J’en vois certains dans le fond qui me diront “Il peut y avoir des effets de bord si on écrit comme ça !”
Oui, je sais. Ça s’appelle une accroche ;) d’ailleurs, tu as cliqué sur l'article 😁
Ici aucune évaluation n’est faite, je rappelle que le préprocesseur n’effectue que du remplacement de texte, donc
PRODUCT(x+1, y-2) va se résoudre en (x+1*y-2) …
En utilisant des parenthèses :
#define PRODUCT(a, b) ((a)*(b))
On obtient : ((x+1)*(y-2)) ! Yay!
Maintenant que je vous tiens, voyons un autre cas
#define FOOBAR() foo(); bar()
Cette macro permet effectivement de remplacer l’appel de FOOBAR par 2 appels de fonctions successifs…
Sauf pour les hérétiques qui utilisent des if sans accolades 😁
if (condition) FOOBAR();
L’appel de la fonction bar() ne sera pas soumise au if !
Facile ! il suffit de rajouter des accolades dans la macro :
#define FOOBAR() { foo(); bar(); }
Maintenant, ce qui risque poser un problème, c’est le else
if(condition)
FOOBAR();
else
do_stuff();
car mettre un ; après les accolades d’un if déconnecte le else du if et génère une erreur de syntaxe.
Parce qu’on ne sait jamais qui va utiliser notre code, il vaut mieux parer à toute éventualité 🙂
Une convention pour se prémunir de tout problème, surtout dans le cas de multi-instructions dans une macro, est d’utiliser la syntaxe suivante :
#define FOOBAR() do{ foo(); bar(); }while(0)
Cette écriture a l’avantage d’ajouter un bloc qui contient vos instructions, pour des macros complexes, et est compatible avec tous les cas cités plus haut 🙂
Pour cette raison, vous pouvez croiser cette écriture, même pour des macros simples.
À vos claviers ;)
