C++ Préprocesseur

Les préprocesseurs sont des directives qui indiquent au compilateur d'effectuer le prétraitement requis avant la compilation proprement dite.

Toutes les directives de préprocesseur commencent par le signe dièse (#). Seuls des caractères d'espacement peuvent apparaître avant une directive de préprocesseur. Les directives de préprocesseur ne sont pas des instructions C++, elles ne se terminent donc pas par un point-virgule (;).

Nous avons vu que dans tous les exemples précédents,#includedirective. Cette macro est utilisée pour inclure un fichier d'en-tête dans le fichier source.

C++ prend également en charge de nombreuses directives de préprocesseur, telles que #include, #define, #if, #else, #line, etc. Examinons ces directives importantes.

#define Préprocesseur

La directive de préprocesseur #define est utilisée pour créer des constantes symboliques. Cette constante symbolique est souvent appeléemacrola forme générale de la directive est :

#define macro-name replacement-text 

Lorsque cette ligne de code apparaît dans un fichier, toutes les occurrences ultérieures de la macro dans ce fichier seront remplacées par le texte de remplacement avant que le programme ne soit compilé. Par exemple :

#include <iostream> using namespace std; #define PI 3.14159 int main () { cout << "Valeur de PI :" << PI << endl; return 0; }

Maintenant, testons ce code pour voir le résultat du prétraitement. En supposant que le fichier de code source existe déjà, utilisez ensuite l'option -E pour compiler et rediriger le résultat vers test.p. Maintenant, si vous regardez le fichier test.p, vous verrez qu'il contient déjà une grande quantité d'informations, et que la valeur en bas du fichier a été modifiée comme suit :

$ gcc -E test.cpp > test.p

...
int main ()
{
 
    cout << "Value of PI :" << 3.14159 << endl; 

    return 0;
}

Macro paramétrée

Vous pouvez utiliser #define pour définir une macro avec des paramètres, comme suit :

#include <iostream> using namespace std; #define MIN(a,b) (a<b ? a : b) int main () { int i, j; i = 100; j = 30; cout <<"La plus petite valeur est :" << MIN(i, j) << endl; return 0; }

Lorsque le code ci-dessus est compilé et exécuté, il produit les résultats suivants :

较小的值为:30

Compilation conditionnelle

Il existe plusieurs directives qui peuvent être utilisées pour compiler sélectivement des parties du code source du programme. Ce processus est appelé compilation conditionnelle.

La structure du préprocesseur conditionnel est très similaire à la structure de sélection if. Jetez un œil au code de préprocesseur suivant :

#ifdef NULL
   #define NULL 0
#endif

Vous pouvez compiler uniquement pendant le débogage. Le commutateur de débogage peut être implémenté avec une macro, comme suit :

#ifdef DEBUG
   cerr <<"Variable x = " << x << endl;
#endif

Si la constante symbolique DEBUG a été définie avant la directive #ifdef DEBUG, alors les instructions dans le programmecerrinstructions seront compilées. Vous pouvez utiliser l'instruction #if 0 pour commenter une partie du programme, comme suit :

#if 0
   不进行编译的代码
#endif

Essayons l'exemple suivant :

Exemple

#include <iostream> using namespace std; #define DEBUG #define MIN(a,b) (((a)<(b)) ? a : b) int main () { int i, j; i = 100; j = 30; #ifdef DEBUG cerr <<"Trace: Inside main function" << endl; #endif #if 0 /*Ceci est la section de commentaires*/ cout << MKSTR(HELLO C++) << endl; #endif cout <<"The minimum is " << MIN(i, j) << endl; #ifdef DEBUG cerr <<"Trace : Sortie de la fonction main" << endl; #endif return 0; }

Lorsque le code ci-dessus est compilé et exécuté, il produit les résultats suivants :

Trace: Inside main function
The minimum is 30
Trace: Coming out of main function

Les opérateurs # et ##

Les opérateurs de préprocesseur # et ## sont disponibles à la fois en C++ et en C ANSI/ISO. L'opérateur # convertit un jeton de texte de remplacement en une chaîne entre guillemets.

Considérez la définition de macro suivante :

Exemple

#include <iostream> using namespace std; #define MKSTR( x ) #x int main () { cout << MKSTR(HELLO C++) << endl; return 0; }

Lorsque le code ci-dessus est compilé et exécuté, il produit les résultats suivants :

HELLO C++

Regardons comment cela fonctionne. Il n'est pas difficile de comprendre que le préprocesseur C++ prend la ligne suivante :

cout << MKSTR(HELLO C++) << endl;

Converti en :

cout << "HELLO C++" << endl;

L'opérateur ## est utilisé pour concaténer deux jetons. Voici un exemple :

#define CONCAT( x, y )  x ## y

Lorsque CONCAT apparaît dans le programme, ses arguments sont concaténés et utilisés pour remplacer la macro. Par exemple, CONCAT(HELLO, C++) dans le programme serait remplacé par "HELLO C++", comme le montre l'exemple ci-dessous.

Exemple

#include <iostream> using namespace std; #define concat(a, b) a ## b int main() { int xy = 100; cout << concat(x, y); return 0; }

Lorsque le code ci-dessus est compilé et exécuté, il produit les résultats suivants :

100

Regardons comment cela fonctionne. Il n'est pas difficile de comprendre que le préprocesseur C++ prend la ligne suivante :

cout << concat(x, y);

Converti en :

cout << xy;

Macros prédéfinies en C++

C++ fournit quelques macros prédéfinies présentées dans le tableau suivant :

Macro Description
__LINE__ Cela inclura le numéro de ligne actuel lorsque le programme est compilé.
__FILE__ Cela inclura le nom du fichier actuel lorsque le programme est compilé.
__DATE__ Cela inclura une chaîne de caractères sous la forme mois/jour/année, qui représente la date à laquelle le fichier source est converti en code objet.
__TIME__ Cela inclura une chaîne au format heure:minute:seconde, qui représente l'heure à laquelle le programme a été compilé.

Regardons les exemples des macros ci-dessus :

Exemple

#include <iostream> using namespace std; int main () { cout << "Valeur de __LINE__ : " << __LINE__ << endl; cout << "Valeur de __FILE__ : " << __FILE__ << endl; cout << "Valeur de __DATE__ : " << __DATE__ << endl; cout << "Valeur de __TIME__ : " << __TIME__ << endl; return 0; }

Lorsque le code ci-dessus est compilé et exécuté, il produit les résultats suivants :

Value of __LINE__ : 6
Value of __FILE__ : test.cpp
Value of __DATE__ : Feb 28 2011
Value of __TIME__ : 18:52:48
autres extensions