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

La directive #if , avec les directives #elif, #elseet #endif , contrôle la compilation des parties d’un fichier source.The #if directive, with the #elif, #else, and #endif directives, controls compilation of portions of a source file. Si l’expression que vous écrivez (après le #if) a une valeur différente de zéro, le groupe de lignes qui suit immédiatement la directive #if est conservé dans l’unité de traduction.If the expression you write (after the #if) has a nonzero value, the line group immediately following the #if directive is kept in the translation unit.

GrammaireGrammar

Conditional : conditional :
    If-part Elif-partsOPT else-partOPT endif-Line    if-part elif-partsopt else-partopt endif-line

If-part : if-part :
    texte if-Line    if-line text

If-Line : if-line :
    #if expression constante #if    #if constant-expression
    #ifdef identificateur de #ifdef    #ifdef identifier
    #ifndef identificateur de #ifndef    #ifndef identifier

Elif-parties : elif-parts :
    texte de ligne Elif    elif-line text
    Elif-parties Elif-texte de ligne    elif-parts elif-line text

Elif-ligne : elif-line :
    *#elif***expression constante #elif     #elif constant-expression

else-part : else-part :
    texte de ligne Else    else-line text

else-ligne : else-line :
    #else    #else

endif-ligne : endif-line :
    #endif    #endif

NotesRemarks

Chaque #if directive d’un fichier source doit être mise en correspondance par une directive de #endif de fermeture.Each #if directive in a source file must be matched by a closing #endif directive. N’importe quel nombre de directives #elif peut apparaître entre les directives #if et #endif , mais au plus une directive #else est autorisée.Any number of #elif directives can appear between the #if and #endif directives, but at most one #else directive is allowed. La directive #else , le cas échéant, doit être la dernière directive avant #endif.The #else directive, if present, must be the last directive before #endif.

Les directives #if, #elif, #elseet #endif peuvent être imbriquées dans les parties de texte d’autres directives de #if .The #if, #elif, #else, and #endif directives can nest in the text portions of other #if directives. Chaque directive #else, #elifou #endif imbriquée appartient à la directive #if précédente la plus proche.Each nested #else, #elif, or #endif directive belongs to the closest preceding #if directive.

Toutes les directives de compilation conditionnelle, telles que #if et #ifdef, doivent correspondre à une directive de #endif de fermeture avant la fin du fichier.All conditional-compilation directives, such as #if and #ifdef, must match a closing #endif directive before the end of file. Dans le cas contraire, un message d’erreur est généré.Otherwise, an error message is generated. 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.When conditional-compilation directives are contained in include files, they must satisfy the same conditions: There must be no unmatched conditional-compilation directives at the end of the include file.

Le remplacement de macro est effectué dans la partie de la ligne qui suit une commande #elif , de sorte qu’un appel de macro peut être utilisé dans l' expression constante.Macro replacement is done within the part of the line that follows an #elif command, so a macro call can be used in the constant-expression.

Le préprocesseur sélectionne l’une des occurrences de texte données pour un traitement ultérieur.The preprocessor selects one of the given occurrences of text for further processing. Un bloc spécifié dans le texte peut être n’importe quelle séquence de texte.A block specified in text can be any sequence of text. Il peut occuper plusieurs lignes.It can occupy more than one line. Généralement, le texte est un texte de programme qui a une signification pour le compilateur ou le préprocesseur.Usually text is program text that has meaning to the compiler or the preprocessor.

Le préprocesseur traite le texte sélectionné et le transmet au compilateur.The preprocessor processes the selected text and passes it to the compiler. Si le texte contient des directives de préprocesseur, le préprocesseur exécute ces directives.If text contains preprocessor directives, the preprocessor carries out those directives. Seuls les blocs de texte sélectionnés par le préprocesseur sont compilés.Only text blocks selected by the preprocessor are compiled.

Le préprocesseur sélectionne un seul élément de texte en évaluant l’expression constante qui suit chaque #if ou #elif directive jusqu’à ce qu’il trouve une expression constante vraie (différente de zéro).The preprocessor selects a single text item by evaluating the constant expression following each #if or #elif directive until it finds a true (nonzero) constant expression. Il sélectionne tout le texte (y compris les autres directives de préprocesseur commençant par # ) jusqu’à son #elif, #elseou #endifassocié.It selects all text (including other preprocessor directives beginning with #) up to its associated #elif, #else, or #endif.

Si toutes les occurrences de constant-expression ont la valeur false, ou si aucune directive #elif n’apparaît, le préprocesseur sélectionne le bloc de texte après la clause #else .If all occurrences of constant-expression are false, or if no #elif directives appear, the preprocessor selects the text block after the #else clause. Lorsqu’il n’existe aucune clause #else , et que toutes les instances de constant-expression dans le bloc #if ont la valeur false, aucun bloc de texte n’est sélectionné.When there's no #else clause, and all instances of constant-expression in the #if block are false, no text block is selected.

L' expression constante est une expression constante entière avec les restrictions supplémentaires suivantes :The constant-expression is an integer constant expression with these additional restrictions:

  • Les expressions doivent avoir un type intégral et ne peuvent inclure que des constantes entières, des constantes caractère et l’opérateur défini .Expressions must have integral type and can include only integer constants, character constants, and the defined operator.

  • L’expression ne peut pas utiliser sizeof ou un opérateur de cast de type.The expression can't use sizeof or a type-cast operator.

  • L’environnement cible peut ne pas être en mesure de représenter toutes les plages d’entiers.The target environment may be unable to represent all ranges of integers.

  • La traduction représente int le type de la même façon que le type long , et de unsigned int la même façon que unsigned long .The translation represents type int the same way as type long, and unsigned int the same way as 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.The translator can translate character constants to a set of code values different from the set for the target environment. Pour déterminer les propriétés de l’environnement cible, utilisez une application générée pour cet environnement afin de vérifier les valeurs des *limites. *Macros H.To determine the properties of the target environment, use an app built for that environment to check the values of the LIMITS.H macros.

  • L’expression ne doit pas interroger l’environnement et doit rester isolée des détails d’implémentation sur l’ordinateur cible.The expression must not query the environment, and must remain insulated from implementation details on the target computer.

Opérateurs de préprocesseurPreprocessor operators

définidefined

L’opérateur de préprocesseur défini peut être utilisé dans des expressions constantes spéciales, comme indiqué dans la syntaxe suivante :The preprocessor operator defined can be used in special constant expressions, as shown by the following syntax:

defined ( identificateur )defined( identifier )
defined identificateur définidefined identifier

Cette expression constante est considérée comme vraie (différente de zéro) si l' identificateur est actuellement défini.This constant expression is considered true (nonzero) if the identifier is currently defined. Sinon, la condition n'est pas vérifiée (0).Otherwise, the condition is false (0). Un identificateur défini comme du texte vide est considéré comme défini.An identifier defined as empty text is considered defined. L’opérateur défini peut être utilisé dans une #if et une directive #elif , mais nulle part ailleurs.The defined operator can be used in an #if and an #elif directive, but nowhere else.

Dans l’exemple suivant, les directives #if et #endif contrôlent la compilation de l’un des trois appels de fonction :In the following example, the #if and #endif directives control compilation of one of three function calls:

#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.The function call to credit is compiled if the identifier CREDIT is defined. Si l'identificateur DEBIT est défini, l'appel de fonction à debit est compilé.If the identifier DEBIT is defined, the function call to debit is compiled. Si aucun de ces deux identificateurs n'est défini, l'appel de printerror est compilé.If neither identifier is defined, the call to printerror is compiled. CREDITEt credit sont des identificateurs distincts en C et C++, car leurs cas sont différents.Both CREDIT and credit are distinct identifiers in C and C++ because their cases are different.

Les instructions de compilation conditionnelle dans l'exemple suivant supposent une constante symbolique définie au préalable et nommée DLEVEL.The conditional compilation statements in the following example assume a previously defined symbolic constant named 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 montre deux ensembles de directives #if, #elseet #endif imbriquées.The first #if block shows two sets of nested #if, #else, and #endif directives. Le premier jeu de directives est traité uniquement si DLEVEL > 5 a la valeur true.The first set of directives is processed only if DLEVEL > 5 is true. Sinon, les instructions situées après #else sont traitées.Otherwise, the statements after #else are processed.

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 .The #elif and #else directives in the second example are used to make one of four choices, based on the value of DLEVEL. La constante STACK a la valeur 0, 100 ou 200, selon la définition de DLEVEL.The constant STACK is set to 0, 100, or 200, depending on the definition of DLEVEL. Si DLEVEL est supérieur à 5, l'instructionIf DLEVEL is greater than 5, then the statement

#elif DLEVEL > 5
display(debugptr);

est compilé et STACK n’est pas défini.is compiled, and STACK isn't defined.

Une utilisation courante de la compilation conditionnelle consiste à empêcher plusieurs inclusions du même fichier d'en-tête.A common use for conditional compilation is to prevent multiple inclusions of the same header file. En C++, où les classes sont souvent définies dans les fichiers d’en-tête, les constructions comme celle-ci peuvent être utilisées pour empêcher plusieurs définitions :In C++, where classes are often defined in header files, constructs like this one can be used to prevent multiple definitions:

/*  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.The preceding code checks to see if the symbolic constant EXAMPLE_H is defined. Dans ce cas, le fichier a déjà été inclus et n’a pas besoin d’être retraité.If so, the file has already been included and doesn't need reprocessing. Sinon, la constante EXAMPLE_H est définie pour marquer EXAMPLE.H comme déjà traité.If not, the constant EXAMPLE_H is defined to mark EXAMPLE.H as already processed.

__has_include__has_include

Visual Studio 2017 version 15,3 et versions ultérieures: détermine si un en-tête de bibliothèque peut être inclus :Visual Studio 2017 version 15.3 and later: Determines whether a library header is available for 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 aussiSee also

Directives de préprocesseurPreprocessor directives