C - Préprocesseurs

le C Preprocessorne fait pas partie du compilateur, mais constitue une étape distincte du processus de compilation. En termes simples, un préprocesseur C n'est qu'un outil de substitution de texte et il demande au compilateur d'effectuer le prétraitement requis avant la compilation proprement dite. Nous appellerons le préprocesseur C CPP.

Toutes les commandes du préprocesseur commencent par un symbole de hachage (#). Il doit s'agir du premier caractère non vide, et pour la lisibilité, une directive de préprocesseur doit commencer dans la première colonne. La section suivante répertorie toutes les directives importantes du préprocesseur -

N ° Sr. Directive et description
1

#define

Remplace une macro de préprocesseur.

2

#include

Insère un en-tête particulier d'un autre fichier.

3

#undef

Annule la définition d'une macro de préprocesseur.

4

#ifdef

Renvoie true si cette macro est définie.

5

#ifndef

Renvoie true si cette macro n'est pas définie.

6

#if

Teste si une condition de compilation est vraie.

sept

#else

L'alternative pour #if.

8

#elif

#else et #if dans une seule instruction.

9

#endif

Termine le préprocesseur conditionnel.

dix

#error

Imprime un message d'erreur sur stderr.

11

#pragma

Emet des commandes spéciales au compilateur, en utilisant une méthode standardisée.

Exemples de préprocesseurs

Analysez les exemples suivants pour comprendre diverses directives.

#define MAX_ARRAY_LENGTH 20

Cette directive indique au CPP de remplacer les instances de MAX_ARRAY_LENGTH par 20. Utilisez #define pour les constantes afin d'augmenter la lisibilité.

#include <stdio.h>
#include "myheader.h"

Ces directives indiquent au CPP d'obtenir stdio.h depuis System Librarieset ajoutez le texte au fichier source actuel. La ligne suivante indique au RPC d'obtenirmyheader.h à partir du répertoire local et ajoutez le contenu au fichier source actuel.

#undef  FILE_SIZE
#define FILE_SIZE 42

Il indique au CPP d'annuler la définition de FILE_SIZE existant et de le définir comme 42.

#ifndef MESSAGE
   #define MESSAGE "You wish!"
#endif

Il indique au CPP de définir MESSAGE uniquement si MESSAGE n'est pas déjà défini.

#ifdef DEBUG
   /* Your debugging statements here */
#endif

Il indique au CPP de traiter les instructions jointes si DEBUG est défini. Ceci est utile si vous passez l' indicateur -DDEBUG au compilateur gcc au moment de la compilation. Cela définira DEBUG, vous pouvez donc activer et désactiver le débogage à la volée pendant la compilation.

Macros prédéfinies

ANSI C définit un certain nombre de macros. Bien que chacun soit disponible pour une utilisation en programmation, les macros prédéfinies ne doivent pas être directement modifiées.

N ° Sr. Macro et description
1

__DATE__

La date actuelle sous forme de littéral de caractères au format "MMM JJ AAAA".

2

__TIME__

L'heure actuelle sous forme de littéral de caractère au format "HH: MM: SS".

3

__FILE__

Celui-ci contient le nom de fichier actuel sous forme de chaîne littérale.

4

__LINE__

Celui-ci contient le numéro de ligne actuel sous forme de constante décimale.

5

__STDC__

Défini comme 1 lorsque le compilateur est conforme à la norme ANSI.

Essayons l'exemple suivant -

#include <stdio.h>

int main() {

   printf("File :%s\n", __FILE__ );
   printf("Date :%s\n", __DATE__ );
   printf("Time :%s\n", __TIME__ );
   printf("Line :%d\n", __LINE__ );
   printf("ANSI :%d\n", __STDC__ );

}

Lorsque le code ci-dessus dans un fichier test.c est compilé et exécuté, il produit le résultat suivant -

File :test.c
Date :Jun 2 2012
Time :03:36:24
Line :8
ANSI :1

Opérateurs de préprocesseur

Le préprocesseur C offre les opérateurs suivants pour aider à créer des macros -

L'opérateur Macro Continuation (\)

Une macro est normalement limitée à une seule ligne. L'opérateur de continuation de macro (\) est utilisé pour continuer une macro qui est trop longue pour une seule ligne. Par exemple -

#define  message_for(a, b)  \
   printf(#a " and " #b ": We love you!\n")

L'opérateur Stringize (#)

L'opérateur stringize ou number-sign ('#'), lorsqu'il est utilisé dans une définition de macro, convertit un paramètre de macro en une constante de chaîne. Cet opérateur ne peut être utilisé que dans une macro ayant un argument ou une liste de paramètres spécifié. Par exemple -

#include <stdio.h>

#define  message_for(a, b)  \
   printf(#a " and " #b ": We love you!\n")

int main(void) {
   message_for(Carole, Debra);
   return 0;
}

Lorsque le code ci-dessus est compilé et exécuté, il produit le résultat suivant -

Carole and Debra: We love you!

L'opérateur de collage de jetons (##)

L'opérateur de collage de jetons (##) dans une définition de macro combine deux arguments. Il permet à deux jetons distincts dans la définition de macro d'être joints en un seul jeton. Par exemple -

#include <stdio.h>

#define tokenpaster(n) printf ("token" #n " = %d", token##n)

int main(void) {
   int token34 = 40;
   tokenpaster(34);
   return 0;
}

Lorsque le code ci-dessus est compilé et exécuté, il produit le résultat suivant -

token34 = 40

Cela s'est produit parce que cet exemple donne la sortie réelle suivante du préprocesseur -

printf ("token34 = %d", token34);

Cet exemple montre la concaténation du token ## n en token34 et ici nous avons utilisé les deux stringize et token-pasting.

L'opérateur Defined ()

Le préprocesseur definedL'opérateur est utilisé dans les expressions constantes pour déterminer si un identificateur est défini à l'aide de #define. Si l'identificateur spécifié est défini, la valeur est true (non nulle). Si le symbole n'est pas défini, la valeur est false (zéro). L'opérateur défini est spécifié comme suit -

#include <stdio.h>

#if !defined (MESSAGE)
   #define MESSAGE "You wish!"
#endif

int main(void) {
   printf("Here is the message: %s\n", MESSAGE);  
   return 0;
}

Lorsque le code ci-dessus est compilé et exécuté, il produit le résultat suivant -

Here is the message: You wish!

Macros paramétrées

L'une des fonctions puissantes du CPP est la possibilité de simuler des fonctions à l'aide de macros paramétrées. Par exemple, nous pourrions avoir du code pour mettre un nombre au carré comme suit -

int square(int x) {
   return x * x;
}

Nous pouvons réécrire au-dessus du code en utilisant une macro comme suit -

#define square(x) ((x) * (x))

Les macros avec des arguments doivent être définies à l'aide du #definedirective avant de pouvoir les utiliser. La liste d'arguments est placée entre parenthèses et doit suivre immédiatement le nom de la macro. Les espaces ne sont pas autorisés entre le nom de la macro et les parenthèses ouvertes. Par exemple -

#include <stdio.h>

#define MAX(x,y) ((x) > (y) ? (x) : (y))

int main(void) {
   printf("Max between 20 and 10 is %d\n", MAX(10, 20));  
   return 0;
}

Lorsque le code ci-dessus est compilé et exécuté, il produit le résultat suivant -

Max between 20 and 10 is 20