#if、#elif、#else、および #endif ディレクティブ (C/C++)#if, #elif, #else, and #endif directives (C/C++)

#Ifディレクティブは、 #elif#else、および #endifディレクティブを使用して、ソースファイルの一部のコンパイルを制御します。The #if directive, with the #elif, #else, and #endif directives, controls compilation of portions of a source file. ( #Ifの後に) 記述する式が0以外の値を持つ場合、 #ifディレクティブの直後の行グループが翻訳単位に保持されます。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.

文法Grammar

条件: conditional :
    if-パート elif-parts選択else-パート選択endif-行    if-part elif-partsopt else-partopt endif-line

if-part : if-part :
    行のテキスト    if-line text

改行: if-line :
     #if 定数式    #if constant-expression
     #ifdef 識別子    #ifdef identifier
     #ifndef identifier    #ifndef identifier

elif-parts : elif-parts :
    elif 行のテキスト    elif-line text
    elif-部分テキスト    elif-parts elif-line text

elif 行: elif-line :
     #elif constant-expression    #elif constant-expression

else-パート: else-part :
    他の行のテキスト    else-line text

他の行: else-line :
     #else    #else

endif-行: endif-line :
     #endif    #endif

RemarksRemarks

ソースファイル内の各 #ifディレクティブは、終了 #endifディレクティブで一致する必要があります。Each #if directive in a source file must be matched by a closing #endif directive. #Ifディレクティブと #endifディレクティブの間には、任意の数の #elifディレクティブを含めることができますが、最大で1つの #elseディレクティブを使用できます。Any number of #elif directives can appear between the #if and #endif directives, but at most one #else directive is allowed. #Elseディレクティブ (存在する場合) は、 #endifする前に最後のディレクティブである必要があります。The #else directive, if present, must be the last directive before #endif.

#If#elif#else、および #endifディレクティブは、他の #ifディレクティブのテキスト部分で入れ子にすることができます。The #if, #elif, #else, and #endif directives can nest in the text portions of other #if directives. 入れ子になった各 #else#elif、または #endifディレクティブは、最も近い前の #ifディレクティブに属します。Each nested #else, #elif, or #endif directive belongs to the closest preceding #if directive.

#If#ifdefなど、すべての条件付きコンパイルディレクティブは、ファイルの終わりの前にある #endifディレクティブの終わりと一致する必要があります。All conditional-compilation directives, such as #if and #ifdef, must match a closing #endif directive before the end of file. それ以外の場合は、エラーメッセージが生成されます。Otherwise, an error message is generated. 条件付きコンパイルディレクティブがインクルードファイルに含まれている場合は、同じ条件を満たす必要があります。インクルードファイルの末尾に、一致しない条件付きコンパイルディレクティブを指定することはできません。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.

マクロの置換は、 #elifコマンドの後の行の部分で行われるため、定数式でマクロ呼び出しを使用できます。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.

プリプロセッサは、指定されたいずれかのテキストを選択して、後続の処理を行います。The preprocessor selects one of the given occurrences of text for further processing. テキストで指定されたブロックは、任意のテキストシーケンスにすることができます。A block specified in text can be any sequence of text. 複数行にまたがる場合があります。It can occupy more than one line. 通常、 textはコンパイラまたはプリプロセッサに対して意味のあるプログラムテキストです。Usually text is program text that has meaning to the compiler or the preprocessor.

プリプロセッサは、選択されたテキストを処理し、コンパイラに渡します。The preprocessor processes the selected text and passes it to the compiler. テキストにプリプロセッサディレクティブが含まれている場合、プリプロセッサはこれらのディレクティブを実行します。If text contains preprocessor directives, the preprocessor carries out those directives. プリプロセッサによって選択されたテキスト ブロックだけがコンパイルされます。Only text blocks selected by the preprocessor are compiled.

プリプロセッサは、true (0 以外) の定数式が見つかるまで、各 #ifまたは #elifディレクティブの後に続く定数式を評価することによって、1つのテキスト項目を選択します。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. このメソッドは、関連付けられて # いる #elif#else、または #endifまで、すべてのテキスト (で始まる他のプリプロセッサディレクティブを含む) を選択します。It selects all text (including other preprocessor directives beginning with #) up to its associated #elif, #else, or #endif.

すべての定数式が false の場合、または #elifディレクティブがない場合、プリプロセッサは #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. #Else句がなく、 #ifブロック内の定数式のすべてのインスタンスが false の場合、テキストブロックは選択されません。When there's no #else clause, and all instances of constant-expression in the #if block are false, no text block is selected.

定数式は、次の追加の制限付き整数定数式です。The constant-expression is an integer constant expression with these additional restrictions:

  • 式には整数型を指定する必要があり、整数定数、文字定数、および定義された演算子のみを含めることができます。Expressions must have integral type and can include only integer constants, character constants, and the defined operator.

  • 式では、 sizeofまたは型キャスト演算子を使用できません。The expression can't use sizeof or a type-cast operator.

  • ターゲット環境は、整数のすべての範囲を表すことができない可能性があります。The target environment may be unable to represent all ranges of integers.

  • 変換は、 long型と同じ方法でint型を表します。符号なし intunsigned longと同じように解釈されます。The translation represents type int the same way as type long, and unsigned int the same way as unsigned long.

  • トランスレーターは、ターゲット環境とは別のコード値のセットに文字定数を翻訳できます。The translator can translate character constants to a set of code values different from the set for the target environment. ターゲット環境のプロパティを確認するには、その環境用にビルドされたアプリを使用して、制限の値を確認します。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.

  • 式は環境に対してクエリを実行することはできません。また、対象のコンピューターで実装の詳細から分離された状態を維持する必要があります。The expression must not query the environment, and must remain insulated from implementation details on the target computer.

プリプロセッサ演算子Preprocessor operators

定義defined

定義されているプリプロセッサ演算子は、次の構文に示すように、特殊な定数式で使用できます。The preprocessor operator defined can be used in special constant expressions, as shown by the following syntax:

定義済み ( 識別子 ) defined( identifier )
定義済み 識別子defined identifier

識別子が現在定義されている場合、この定数式は true (0 以外) と見なされます。This constant expression is considered true (nonzero) if the identifier is currently defined. それ以外の場合、条件は False (0) です。Otherwise, the condition is false (0). 空のテキストとして定義された識別子は、定義されていると見なされます。An identifier defined as empty text is considered defined. 定義された演算子は、 #if#elifディレクティブでは使用できますが、それ以外は使用できません。The defined operator can be used in an #if and an #elif directive, but nowhere else.

次の例では、 #ifディレクティブと #endifディレクティブは、次の3つの関数呼び出しのいずれかのコンパイルを制御します。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

credit の関数呼び出しは、CREDIT 識別子が定義されている場合、コンパイルされます。The function call to credit is compiled if the identifier CREDIT is defined. DEBIT 識別子が定義されている場合、debit の関数呼び出しがコンパイルされます。If the identifier DEBIT is defined, the function call to debit is compiled. どちらの識別子も定義されていない場合、printerror の呼び出しがコンパイルされます。If neither identifier is defined, the call to printerror is compiled. CREDITcreditどちらも C の個別のC++識別子であり、そのケースは異なるためです。Both CREDIT and credit are distinct identifiers in C and C++ because their cases are different.

次の例の条件付きコンパイル ステートメントは、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

最初の #ifブロックには、入れ子になった #if#else、および #endifディレクティブの2つのセットが表示されます。The first #if block shows two sets of nested #if, #else, and #endif directives. 最初のセットのディレクティブは、DLEVEL > 5 が true の場合にのみ処理されます。The first set of directives is processed only if DLEVEL > 5 is true. それ以外の場合は、 #else後のステートメントが処理されます。Otherwise, the statements after #else are processed.

2番目の例の #elifディレクティブと #elseディレクティブは、のDLEVEL値に基づいて4つの選択肢のいずれかを作成するために使用されます。The #elif and #else directives in the second example are used to make one of four choices, based on the value of DLEVEL. STACK の定義により、定数 DLEVEL は 0、100、または 200 に設定されます。The constant STACK is set to 0, 100, or 200, depending on the definition of DLEVEL. DLEVEL が 5 より大きい場合、次のステートメントがコンパイルされます。If DLEVEL is greater than 5, then the statement

#elif DLEVEL > 5
display(debugptr);

はコンパイルされSTACK 、定義されていません。is compiled, and STACK isn't defined.

条件付きコンパイルの一般的な用途は、同じヘッダー ファイルの多重インクルードを防ぐことです。A common use for conditional compilation is to prevent multiple inclusions of the same header file. でC++は、多くの場合、クラスがヘッダーファイルで定義されていますが、次のようなコンストラクトを使用して複数の定義を防ぐことができます。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 )

前のコードは、シンボリック定数 EXAMPLE_H が定義されているかどうかを確認します。The preceding code checks to see if the symbolic constant EXAMPLE_H is defined. その場合、ファイルは既に含まれており、再処理は必要ありません。If so, the file has already been included and doesn't need reprocessing. 定義されていない場合、EXAMPLE.H が処理されてから、EXAMPLE_H が処理済みとマークされます。If not, the constant EXAMPLE_H is defined to mark EXAMPLE.H as already processed.

__has_include__has_include

Visual Studio 2017 バージョン 15.3 およびそれ以降:ライブラリヘッダーを含めることができるかどうかを判断します。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

関連項目See also

プリプロセッサディレクティブPreprocessor directives