Partager via


#if, #elif, #else et #endif, directives (C/C++)

La directive #if, avec les directives #elif, #else et #endif, contrôle la compilation des parties d’un fichier source. Si l’expression que vous écrivez (après l '#if) a une valeur différente de zéro, le groupe de lignes suivant immédiatement la directive #if est conservé dans l’unité de traduction.

Grammaire

conditionnel :
if-part elif-partsopt else-partopt endif-line

if-part :
texte if-line

if-line :
#if constante-expression
identificateur de #ifdef
identificateur de #ifndef

elif-parts :
texte elif-line
elif-parts elif-line text

elif-line :
expression constante #elif

else-part :
texte de ligne else

else-line :
#else

endif-line :
#endif

Notes

Chaque directive #if dans un fichier source doit être mise en correspondance par une directive de #endif fermante. N’importe quel nombre de directives #elif peuvent apparaître entre les directives #if et #endif , mais au plus une directive #else est autorisée. La directive #else , le cas échéant, doit être la dernière directive avant #endif.

Les directives #if, #elif, #else et #endif peuvent être imbriquées dans les parties texte d’autres directives #if. Chaque directive #else imbriquée, #elif ou #endif appartient à la directive #if la plus proche.

Toutes les directives de compilation conditionnelle, telles que #if et #ifdef, doivent correspondre à une directive de #endif fermante avant la fin du fichier. Sinon, un message d’erreur est généré. Lorsque les directives de compilation conditionnelle sont contenues dans les fichiers Include, elles doivent satisfaire aux mêmes conditions : il ne doit y avoir aucune directive de compilation conditionnelle sans correspondance à la fin du fichier Include.

Le remplacement de macro est effectué dans la partie de la ligne qui suit une commande #elif, afin qu’un appel de macro puisse être utilisé dans l’expression constante.

Le préprocesseur sélectionne l’une des occurrences de texte données pour un traitement ultérieur. Un bloc spécifié dans le texte peut être n’importe quelle séquence de texte. Il peut occuper plusieurs lignes. En règle générale , le texte est un texte de programme qui a une signification pour le compilateur ou le préprocesseur.

Le préprocesseur traite le texte sélectionné et le transmet au compilateur. Si le texte contient des directives de préprocesseur, le préprocesseur exécute ces directives. Seuls les blocs de texte sélectionnés par le préprocesseur sont compilés.

Le préprocesseur sélectionne un seul élément de texte en évaluant l’expression constante qui suit chaque #if ou directive #elif jusqu’à ce qu’elle trouve une expression constante vraie (différente de zéro). Il sélectionne tout le texte (y compris d’autres directives de préprocesseur commençant #par ) jusqu’à son #elif associé, #else ou #endif.

Si toutes les occurrences d’expression constante sont false ou si aucune directive #elif n’apparaît, le préprocesseur sélectionne le bloc de texte après la clause #else. Lorsqu’il n’existe aucune clause #else et que toutes les instances d’expression constante dans le bloc #if sont false, aucun bloc de texte n’est sélectionné.

L’expression constante est une expression constante entière avec ces restrictions supplémentaires :

  • Les expressions doivent avoir un type intégral et peuvent inclure uniquement des constantes entières, des constantes de caractères et l’opérateur défini .

  • L’expression ne peut pas utiliser sizeof ou un opérateur de cast de type.

  • L’environnement cible peut ne pas représenter toutes les plages d’entiers.

  • La traduction représente le type int de la même façon que le type long, et unsigned int de la même façon que unsigned long.

  • Le traducteur peut traduire les constantes caractère en un ensemble de valeurs de code différentes de l'ensemble de l'environnement cible. Pour déterminer les propriétés de l’environnement cible, utilisez une application créée pour cet environnement pour vérifier les valeurs des LIMITES. Macros H .

  • L’expression ne doit pas interroger l’environnement et doit rester isolée des détails de l’implémentation sur l’ordinateur cible.

Opérateurs de préprocesseur

défini

L’opérateur de préprocesseur défini peut être utilisé dans des expressions constantes spéciales, comme illustré par la syntaxe suivante :

defined( identificateur )
identificateur défini

Cette expression constante est considérée comme vraie (différente de zéro) si l’identificateur est actuellement défini. Sinon, la condition n'est pas vérifiée (0). Un identificateur défini comme du texte vide est considéré comme défini. L’opérateur défini peut être utilisé dans un #if et une directive #elif , mais nulle part ailleurs.

Dans l’exemple suivant, les directives #if et #endif contrôlent la compilation de l’un des trois appels de fonction :

#if defined(CREDIT)
    credit();
#elif defined(DEBIT)
    debit();
#else
    printerror();
#endif

L'appel de fonction à credit est compilé si l'identificateur CREDIT est défini. Si l'identificateur DEBIT est défini, l'appel de fonction à debit est compilé. Si aucun de ces deux identificateurs n'est défini, l'appel de printerror est compilé. Les deux CREDIT et credit sont des identificateurs distincts en C et C++, car leurs cas sont différents.

Les instructions de compilation conditionnelle dans l'exemple suivant supposent une constante symbolique définie au préalable et nommée DLEVEL.

#if DLEVEL > 5
    #define SIGNAL  1
    #if STACKUSE == 1
        #define STACK   200
    #else
        #define STACK   100
    #endif
#else
    #define SIGNAL  0
    #if STACKUSE == 1
        #define STACK   100
    #else
        #define STACK   50
    #endif
#endif
#if DLEVEL == 0
    #define STACK 0
#elif DLEVEL == 1
    #define STACK 100
#elif DLEVEL > 5
    display( debugptr );
#else
    #define STACK 200
#endif

Le premier bloc #if affiche deux ensembles de directives #if imbriquées, #else et #endif. Le premier jeu de directives est traité uniquement si DLEVEL > 5 a la valeur true. Sinon, les instructions après #else sont traitées.

Les directives #elif et #else dans le deuxième exemple sont utilisées pour effectuer l’un des quatre choix, en fonction de la valeur de DLEVEL. La constante STACK a la valeur 0, 100 ou 200, selon la définition de DLEVEL. Si DLEVEL est supérieur à 5, l'instruction

#elif DLEVEL > 5
display(debugptr);

est compilé et STACK n’est pas défini.

Une utilisation courante de la compilation conditionnelle consiste à empêcher plusieurs inclusions du même fichier d'en-tête. En C++, où les classes sont souvent définies dans les fichiers d’en-tête, des constructions comme celle-ci peuvent être utilisées pour empêcher plusieurs définitions :

/*  EXAMPLE.H - Example header file  */
#if !defined( EXAMPLE_H )
#define EXAMPLE_H

class Example
{
    //...
};

#endif // !defined( EXAMPLE_H )

Le code précédent vérifie si la constante symbolique EXAMPLE_H est définie. Si c’est le cas, le fichier a déjà été inclus et n’a pas besoin de retraitement. Sinon, la constante EXAMPLE_H est définie pour marquer EXAMPLE.H comme déjà traité.

__has_include

Visual Studio 2017 version 15.3 et ultérieure : détermine si un en-tête de bibliothèque est disponible pour inclusion :

#ifdef __has_include
#  if __has_include(<filesystem>)
#    include <filesystem>
#    define have_filesystem 1
#  elif __has_include(<experimental/filesystem>)
#    include <experimental/filesystem>
#    define have_filesystem 1
#    define experimental_filesystem
#  else
#    define have_filesystem 0
#  endif
#endif

Voir aussi

Directives de préprocesseur