Préprocesseur C++


Les préprocesseurs sont des instructions qui indiquent au compilateur le prétraitement qui doit être effectué avant la compilation proprement dite.

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

Nous avons vu que tous les exemples précédents ont la directive #include. Cette macro est utilisée pour inclure des fichiers d'en-tête dans les fichiers source.

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

#define preprocessing

La directive de prétraitement #define est utilisée pour créer des constantes symboliques. Cette constante symbolique est généralement appelée la macro La forme générale de l'instruction est :

#define macro-name replacement-text

Lorsque cette ligne de code apparaît dans un fichier, toutes les macros suivantes qui apparaissent dans le fichier seront remplacées. avec du texte de remplacement avant la compilation du programme. Par exemple :

#include <iostream>
using namespace std;

#define PI 3.14159

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

    return 0;
}

Maintenant, testons ce code et voyons les résultats du prétraitement. En supposant que le fichier de code source existe déjà, utilisez l'option -E pour compiler et rediriger les résultats vers test.p. Maintenant, si vous regardez le fichier test.p, vous verrez qu'il contient déjà beaucoup d'informations, et les valeurs au bas du fichier ont été modifiées comme suit :

$gcc -E test.cpp > test.p

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

    return 0;
}

Fonction Macro

Vous pouvez utiliser #define pour définir une macro avec des paramètres comme celui-ci :

#include <iostream>
using namespace std;

#define MIN(a,b) (((a)<(b)) ? a : b)

int main ()
{
   int i, j;
   i = 100;
   j = 30;
   cout <<"The minimum is " << MIN(i, j) << endl;

    return 0;
}

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

The minimum is 30

Compilation conditionnelle

Il existe plusieurs instructions 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. Veuillez consulter le code du préprocesseur suivant :

#ifndef NULL
   #define NULL 0
#endif

Vous ne pouvez compiler que pendant le débogage. Le commutateur de débogage peut être implémenté à l'aide d'une macro, comme indiqué ci-dessous :

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

Si dans la directive #ifdef DEBUG. Si la constante symbolique DEBUG a été définie auparavant, l'instruction cerr dans le programme sera compilée. Vous pouvez commenter une partie du programme en utilisant les instructions #if 0 comme ceci :

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

Essayons l'exemple suivant :

#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
   /* 这是注释部分 */
   cout << MKSTR(HELLO C++) << endl;
#endif

   cout <<"The minimum is " << MIN(i, j) << endl;

#ifdef DEBUG
   cerr <<"Trace: Coming out of main function" << endl;
#endif
    return 0;
}

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

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

Opérateurs # et ## Les opérateurs de préprocesseur

# et ## sont disponibles en C++ et ANSI/ISO C. L'opérateur # convertit le jeton de texte de remplacement en chaîne entre guillemets.

Regardez la définition de la macro ci-dessous :

#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 le résultat suivant :

HELLO C++

Voyons ce que c'est Comment ça marche . Il n'est pas difficile de comprendre que le préprocesseur C++ convertit la ligne suivante :

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

en :

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

## l'opérateur est utilisé pour connecter deux jetons. Voici un exemple :

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

Lorsque CONCAT apparaît dans un programme, ses arguments sont concaténés et utilisés à la place de la macro. Par exemple, CONCAT(HELLO, C++) dans le programme sera remplacé par « HELLO C++ », comme indiqué dans l'exemple ci-dessous.

#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

Voyons comment ça marche. Il n'est pas difficile de comprendre que le préprocesseur C++ convertit la ligne suivante :

cout << concat(x, y);

en :

cout << xy;

Les macros prédéfinies en C++

C++ fournit le tableau suivant Quelques-unes des macros prédéfinies :

描述
__LINE__这会在程序编译时包含当前行号。
__FILE__这会在程序编译时包含当前文件名。
__DATE__这会包含一个形式为 month/day/year 的字符串,它表示把源文件转换为目标代码的日期。
__TIME__这会包含一个形式为 hour:minute:second 的字符串,它表示程序被编译的时间。

Voyons une instance de ces macros ci-dessus :

#include <iostream>
using namespace std;

int main ()
{
    cout << "Value of __LINE__ : " << __LINE__ << endl;
    cout << "Value of __FILE__ : " << __FILE__ << endl;
    cout << "Value of __DATE__ : " << __DATE__ << endl;
    cout << "Value of __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