'>

Les directives du préprocesseur

Les directives du préprocesseur sont des lignes incluses dans le code de nos programmes qui ne sont pas des déclarations de programme, mais des directives pour le préprocesseur. Ces lignes sont toujours précédés par un signe dièse (#). Le préprocesseur est exécuté avant la compilation réelle de code commence donc le préprocesseur digère tous ces directives avant que le code est généré par les déclarations.

Ces directives préprocesseur ne s'étendent que sur une seule ligne de code. Dès qu'un caractère de nouvelle ligne est trouvée, la directive de préprocesseur est considéré à la fin. Aucune virgule (;) est attendue à la fin d'une directive de préprocesseur. La seule façon pour une directive de préprocesseur peut s'étendre à travers plus d'une ligne est en précédant le caractère de nouvelle ligne à la fin de la ligne par une barre oblique inverse (\).

définitions de macros (# define, # undef)
Pour définir des macros préprocesseur nous pouvons utiliser # define. Son format est le suivant:

# Define remplacement de l'identificateur

Lorsque le préprocesseur rencontre cette directive, il remplace toutes les occurrences de l'identificateur dans le reste du code de remplacement. Ce remplacement peut être une expression, une déclaration, un bloc ou tout simplement rien. Le préprocesseur ne comprend pas C + +, il remplace simplement toutes les occurrences de l'identificateur de remplacement.

1
 2
 3


   

 #define TABLE_SIZE 100 int table1[TABLE_SIZE]; int table2[TABLE_SIZE];



Après le préprocesseur a remplacé TABLE_SIZE, le code devient équivalent à:

 1
 2


   

 int table1[100]; int table2[100];



Cette utilisation de # define comme definer constant est déjà connu par nous de tutoriels précédents, mais # define peut travailler aussi avec des paramètres à définir des macros de fonction:



   

 #define getmax(a,b) a>b?a:b



Ce serait remplacer toutes les occurrences de getMax suivie de deux arguments de l'expression de remplacement, mais aussi le remplacement de chaque argument par son identifiant, exactement comme on peut s'y attendre si c'était une fonction:

 1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14


   

 // function macro #include <iostream> using namespace std; #define getmax(a,b) ((a)>(b)?(a):(b)) int main() { int x=5, y; y= getmax(x,2); cout << y << endl; cout << getmax(7,x) << endl; return 0; }

   

  5
  7



Macros définies ne sont pas affectés par la structure de bloc. Une macro dure jusqu'à ce qu'elle n'est pas définie avec la directive de préprocesseur # undef:

 1
 2
 3
 4
 5


   

 #define TABLE_SIZE 100 int table1[TABLE_SIZE]; #undef TABLE_SIZE #define TABLE_SIZE 200 int table2[TABLE_SIZE];



Ceci générera le même code que:

 1
 2


   

 int table1[100]; int table2[200];



définitions de macros de fonctions acceptent deux opérateurs spéciaux (# et # #) dans la séquence de remplacement:
Si l'opérateur # est utilisé avant un paramètre est utilisé dans la séquence de remplacement, ce paramètre est remplacé par une chaîne littérale (comme si elle était placée entre guillemets)

 1
 2


   

 #define str(x) #x cout << str(test);



Ce serait traduit en:



   

 cout << "test" ;



L'opérateur # # concatène deux arguments laissant aucun espace entre eux:

 1
 2


   

 #define glue(a,b) a ## b glue(c,out) << "test" ;



Ce serait également traduit en:



   

 cout << "test" ;



Parce que les remplacements préprocesseur se produisent avant toute C + + vérification de la syntaxe, des définitions de macros peuvent être un élément difficile, mais attention: le code qui s'appuie fortement sur les macros complexes peut sembler obscure à d'autres programmeurs, depuis la syntaxe qu'ils attendent est à plusieurs reprises différent des expressions régulières programmeurs attendent en C + +.

Inclusions conditionnelles (# ifdef, # ifndef, # if, # endif, # else et # elif)

Ces directives permettent d'inclure ou d'éliminer une partie du code d'un programme si une certaine condition est remplie.

# Ifdef permet une section d'un programme à être établi que si la macro qui est spécifié comme paramètre a été défini, quel que soit sa valeur est. Par exemple:

 1
 2
 3


   

 #ifdef TABLE_SIZE int table[TABLE_SIZE]; #endif



Dans ce cas, la ligne de code int tableau [TABLE_SIZE]; est seulement compilé si TABLE_SIZE a été précédemment défini avec # define, indépendamment de sa valeur. Si elle n'a pas été définie, cette ligne ne sera pas inclus dans la compilation du programme.

# Ifndef sert exactement l'inverse: le code entre # ifndef et # endif est uniquement compilé si l'identificateur spécifié n'a pas été défini précédemment. Par exemple:

 1
 2
 3
 4


   

 #ifndef TABLE_SIZE #define TABLE_SIZE 100 #endif int table[TABLE_SIZE];



Dans ce cas, si en arrivant à ce morceau de code, la macro TABLE_SIZE n'a pas encore été défini, il serait défini à une valeur de 100. Si elle existait déjà il garderait sa valeur précédente car la directive # define ne serait pas exécuté.

Le # if, # else et # elif (ie, "else if") directives servent à indiquer une condition à remplir pour que la partie du code qu'ils entourent d'être compilés. La condition qui suit # if ou # elif ne peut évaluer des expressions constantes, y compris les expressions de macro. Par exemple:

 1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14


   

 #if TABLE_SIZE>200 #undef TABLE_SIZE #define TABLE_SIZE 200 #elif TABLE_SIZE<50 #undef TABLE_SIZE #define TABLE_SIZE 50 #else #undef TABLE_SIZE #define TABLE_SIZE 100 #endif int table[TABLE_SIZE];



Remarquez comment la structure entière de # if, # elif et # else directives chaîne se termine par # endif.

Le comportement des # ​​ifdef et # ifndef peut également être réalisé en utilisant les opérateurs spéciaux définis et définis respectivement, en quelque # if ou directive # elif:

 1
 2
 3
 4
 5
 6


   

 #if !defined TABLE_SIZE #define TABLE_SIZE 100 #elif defined ARRAY_SIZE #define TABLE_SIZE ARRAY_SIZE int table[TABLE_SIZE]; #endif



Ligne de commande (# line)
Lorsque nous élaborons un programme et une erreur se produit pendant le processus de compilation, le compilateur affiche un message d'erreur avec des références au nom du fichier dans lequel l'erreur s'est produite et un numéro de ligne, de sorte qu'il est plus facile de trouver le code source de l'erreur.

La directive # line nous permet de contrôler les choses, les numéros de ligne dans les fichiers de code ainsi que le nom du fichier que nous voulons qui apparaît lorsqu'une erreur se produit. Son format est le suivant:

# Numéro de ligne "nom de fichier"

Lorsque le numéro est le nouveau numéro de la ligne qui sera affecté à la ligne de code suivante. Les numéros de ligne des lignes successives seront augmentés, un par un à partir de ce point.

"Filename" est un paramètre optionnel qui permet de redéfinir le nom du fichier qui sera affiché. Par exemple:

 1
 2


   

 #line 20 "assigning variable" int a?;



Ce code va générer une erreur qui s'affiche sous forme d'erreur dans le fichier «variable d'affectation", ligne 20.

Erreur de directive (# erreur)
Cette directive annule le processus de compilation où il se trouve, générant une compilation l'erreur qui peut être spécifié en tant que paramètre:

 1
 2
 3


   

 #ifndef __cplusplus #error A C++ compiler is required! #endif



Cet exemple interrompt le processus de compilation si le nom de la macro __ cplusplus n'est pas défini (ce nom macro est définie par défaut dans tous les compilateurs C + +).

inclusion de fichier source (# include)
Cette directive a également été utilisé assidûment dans d'autres sections de ce tutoriel. Lorsque le préprocesseur trouve une directive # include il le remplace par l'ensemble du contenu du fichier spécifié. Il ya deux façons de spécifier un fichier à inclure:

 1
 2


   

 #include "file" #include <file>



La seule différence entre les deux expressions sont les endroits (répertoires) où le compilateur va chercher le fichier. Dans le premier cas où le nom de fichier est spécifié entre guillemets, le fichier est d'abord recherché dans le même répertoire qui inclut le fichier contenant la directive. Dans le cas où il n'est pas là, le compilateur cherche le fichier dans les répertoires par défaut où il est configuré pour rechercher les fichiers d'en-tête standard.
Si le nom du fichier est enfermée entre équerres <> le fichier est recherché directement là où le compilateur est configuré pour rechercher les fichiers d'en-tête standard. Par conséquent, les fichiers d'en-tête standard sont généralement inclus dans les équerres, tandis que d'autres fichiers d'en-tête spécifiques sont incluses en utilisant des guillemets.

directive Pragma (# pragma)
Cette directive est utilisée pour spécifier diverses options pour le compilateur. Ces options sont spécifiques à la plate-forme et le compilateur que vous utilisez. Consultez le manuel ou la référence de votre compilateur pour plus d'informations sur les paramètres possibles que vous pouvez définir avec # pragma.

Si le compilateur ne supporte pas un argument spécifique pour # pragma, il est ignoré - aucune erreur n'est générée.

Noms de macros prédéfinies
Les noms de macros suivantes sont définies à n'importe quel moment:

macro     valeur
__LINE__     Entier représentant la ligne courante dans le fichier de code source en cours de compilation.
__FILE__     Une chaîne littérale contenant le nom présumée du fichier source en cours de compilation.
__DATE__     Un littéral de chaîne sous la forme "Mmm dd yyyy" contenant la date à laquelle le processus de compilation a commencé.
__TIME__     Un littéral de chaîne sous la forme "hh: mm: ss" contenant l'heure à laquelle le processus de compilation a commencé.
__cplusplus     Une valeur entière. Tous les compilateurs C + + ont cette constante définie à une certaine valeur. Si le compilateur est entièrement compatible avec le standard C + + que sa valeur est supérieure ou égale à 199711L selon la version de la norme sont conformes.

Par exemple:

 1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13


   

 // standard macro names #include <iostream> using namespace std; int main() { cout << "This is the line number " << __LINE__; cout << " of file " << __FILE__ << ".\n" ; cout << "Its compilation began " << __DATE__; cout << " at " << __TIME__ << ".\n" ; cout << "The compiler gives a __cplusplus value of " << __cplusplus; return 0; }

   

  C'est le numéro de la ligne 7 du fichier / home / Jay / stdmacronames.cpp.
  Sa compilation a commencé le 1 novembre 2005 à 10:12:29.
  Le compilateur donne une valeur de cplusplus de __ 1 
Publié par Drupal Study