#define macroName macroValue
#define macroName(macroParams, ...) macroContent
L'instruction #define
permet de définir une macro. Cette macro sera remplacée dans la suite du fichier à traiter
par sa valeur, et ce avant que le compilateur ait la main.
Il n'est pas obligatoire qu'une macro ait une valeur : cela permet notamment de réaliser de la compilation conditionnelle. La compilation conditionnelle consiste à compiler ou non une partie du code en fonction de l'existance ou de la non existance d'une macro. Pour de plus amples informations sur ce sujet, veuillez consulter l'exemple de code sur les instructions #if, #ifdef et #ifndef du preprocesseur.
Enfin, notez qu'une macro peut être paramètrée : dans ce cas elle pourra accepter différents paramètres et s'en servir durant la substitution. Comme la compilation de votre fichier se fait en deux temps (préprocessing puis compilation à proprement parler) il faut souvent se méfier des macros paramètrées (l'exemple ci-dessous illustre ce point).
Note : les noms de macros sont fréquemment écrit en majuscules, bien que cela ne soit qu'une convention.
Il existe un certain nombre de macros qui sont prédéfinies dans le préprocesseur et qui vous permettent de connaître un certain nombre d'informations (nom du fichier en cours de traitement, numéro de ligne de l'instruction en cours, ...). Ces macros ne peuvent en aucun cas être supprimées ou altérées : elles sont donc immuables. Le tableau suivant vous donne le nom de ces macros ainsi que leur développement.
Nom des macros | Développement de la macro associée |
---|---|
__LINE__ |
Se développe en une valeur numérique associée au numéro de la ligne courante dans le code du programme. |
__FILE__ |
Cette macro sera remplacée par le nom du fichier en cours de traitement. |
__DATE__ |
Celle-ci se transformera en une chaîne de caractères contenant la date de traitement du fichier sous un format "Mmm jj aaaa". |
__TIME__ |
De même, se transformera en un chaîne représentant l'heure de traitement du fichier sous le format "hh:mm:ss". |
__STDC__ |
Cette macro n'est définie que si votre compilateur respecte les normes ANSI ou ISO. Si tel est le cas, elle est alors définie à la valeur 1. |
__STDC_VERSION__ |
Cette macro existe que depuis C99 (C ISO 19999) : elle n'est donc non définie pour les anciens compilateur.
En C99 elle renverra la valeur |
__cplusplus |
Cette macro ne sera définie que si vous utilisez une chaîne de compilation C++ et non C. |
#include <stdio.h> /* Une macro simple */ #define MON_PI_A_MOI 3.141592654 /* Une macro paramétrée */ #define MAXI(a, b) ((a)<(b) ? (a) : (b)) /* Testez cette version : la valeur retournée dans l'exemple va changer. Il bien entendu éviter de telles macros ! #define MAXI(a, b) a<b ? a : b */ int main() { int x = 3; int y = 6; int z = MAXI(x, y) + 2; printf( "La valeur de PI vaut : %5.2f\n", MON_PI_A_MOI ); printf( "La valeur de c est %d\n", z ); return 0; }
Si vous décommentez l'autre version de la macro, le résultat calculé ne sera plus 5, mais 3. Pourquoi ? La raison est simple.
En fait, le remplacement de la macro est réalisé par le preprocesseur avant que le compilateur prenne la main. Du coup
le compilateur recevra la ligne de code suivante : int z = x<y ? x : y + 2;
. La priorité des operateurs
explique ensuite que le +2 s'applique que à la valeur retournée dans le cas ou le test est faux.
Conclusion : méfiez-vous des macros paramétrées et, dans tous les cas, utilisez les parenthèses pour forcer l'ordre d'évaluation des opérateurs.
Améliorations / Corrections
Vous avez des améliorations (ou des corrections) à proposer pour ce document : je vous remerçie par avance de m'en faire part, cela m'aide à améliorer le site.
Emplacement :
Description des améliorations :