Participer au site avec un Tip
Rechercher
 

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 :

Instruction du preprocesseur #define

Les instructions du préprocesseur C Les instructions #if / #ifdef / #ifndef


Syntaxe générale

#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 199901L (typée long), en C11 elle renverra la valeur 201112L et en C18 elle renverra la valeur 201710L (oui, je sais, c'est bizarre).

__cplusplus

Cette macro ne sera définie que si vous utilisez une chaîne de compilation C++ et non C.

Faites attention : devant et derrière chaque nom se trouvent
deux caractères _ (blancs soulignés et pas des tirés -).

Exemple de code

#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.

Sujets connexes

Le preprocesseur C
#undef
#if, #ifdef, #ifndef


Les instructions du préprocesseur C Les instructions #if / #ifdef / #ifndef