#if、#elif、#else、および #endif ディレクティブ (DirectX HLSL)
ソース ファイルの一部のコンパイルを制御するプリプロセッサ ディレクティブです。
#if ifCondition ... |
---|
[#elif elifCondition ...] |
[#else ...] |
#endif |
パラメーター
ifCondition
評価対象となる 1 次条件です。このパラメーターの評価結果がゼロ以外の値になる場合は、この #if ディレクティブと、その後に記述されている最初の #elif、#else、または #endif の各ディレクティブとの間のすべてのテキストは、変換単位として保持されます。評価結果がゼロの場合、後続のソース コードは保持されません。この条件では、defined というプリプロセッサ演算子を使用して、特定のプリプロセッサ定数またはマクロが定義されているかどうかを確認できます。この演算子を使用することは、#ifdef を使用することと同じ意味を持ちます。
ifCondition パラメーターの値に対する制約については、「解説」を参照してください。
elifCondition [省略可能]
評価対象となる他の条件です。ifCondition パラメーターとそれより前のすべての #elif ディレクティブの評価結果がゼロになり、このパラメーターの評価結果がゼロ以外の値になる場合は、この #elif ディレクティブと、この後に記述されている最初の #elif、#else、または #endif ディレクティブとの間のすべてのテキストは、変換単位として保持されます。そうでない場合は、以降のソース コードは保持されません。この条件では、defined というプリプロセッサ演算子を使用して、特定のプリプロセッサ定数またはマクロが定義されているかどうかを確認できます。この演算子を使用することは、#ifdef を使用することと同じ意味を持ちます。
elifCondition パラメーターの値に対する制約については、「解説」を参照してください。
解説
ソース ファイル内の各 #if ディレクティブには、対となる #endif ディレクティブが存在している必要があります。#if ディレクティブと #endif ディレクティブの間には、任意の数の #elif ディレクティブを記述できますが、#else ディレクティブは 1 回のみ記述できます。#else ディレクティブを記述する場合、それは #endif の前の最後のディレクティブである必要があります。インクルード ファイルに含まれている条件付きコンパイル ディレクティブは、同じ条件を満たす必要があります。
#if、#elif、#else、および #endif の各ディレクティブは、他の #if ディレクティブのテキスト部分でネストできます。ネストした #else、#elif、または #endif の各ディレクティブは、その前に記述した最も近い #if ディレクティブに属しています。
どの条件の評価結果もゼロ以外の値にならない場合は、プリプロセッサは、#else ディレクティブの後ろのテキスト ブロックを選択します。#else 句が省略されており、どの条件の評価結果もゼロ以外の値にならない場合は、どのテキスト ブロックも選択されません。
ifCondition パラメーターおよび elifCondition パラメーターは、次の要件を満たす必要があります。
- 条件付きコンパイル式は、signed long の値として扱われ、これらの式は、C++ の式と同じ規則に基づいて評価されます。
- 式は整数型を持っている必要があり、整数定数、文字定数、および defined 演算子のみを含むことができます。
- 式では sizeof 演算子や型キャスト演算子を使用できません。
- ターゲット環境では、すべての範囲の整数を表現できない場合があります。
- 変換では、int 型を long 型と同じように表現し、unsigned int を unsigned long と同じように表現します。
- トランスレーターは、文字定数を、ターゲット環境用のセットとは異なるコード値セットに翻訳できます。ターゲット環境のプロパティを特定するには、ターゲット環境用にビルドされたアプリケーションで LIMITS.H 内のマクロの値を確認します。
- 式は、環境に関する問い合わせを実行してはならず、ターゲット コンピューターに関する実装上の詳細から隔離されたままである必要があります。
例
ここでは、条件付きコンパイルのプリプロセッサ ディレクティブの使用法を示す例を説明します。
defined 演算子の使用
次の例は、defined 演算子の使用法を示しています。識別子 CREDIT が定義されている場合は、credit 関数の呼び出しがコンパイルされます。識別子 DEBIT が定義されている場合は、debit 関数の呼び出しがコンパイルされます。どちらの識別子も定義されていない場合は、printerror 関数の呼び出しがコンパイルされます。C および C++ では、"CREDIT" と "credit" は大文字と小文字の違いのため、別々の識別子となります。
#if defined(CREDIT) credit(); #elif defined(DEBIT) debit(); #else printerror(); #endif
ネストされた #if ディレクティブの使用
次の例は、#if ディレクティブをネストする方法を示しています。この例では、DLEVEL という名前のシンボリック定数があらかじめ定義されていることを前提としています。#elif ディレクティブおよび #else ディレクティブを使用し、DLEVEL の値に基づいて 4 つの選択肢のいずれかを選択します。定数 STACK は、DLEVEL の定義に応じて 0、100、または 200 に設定されます。DLEVEL が 5 より大きい場合、STACK は定義されません。
#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
ヘッダー ファイルのインクルードのための使用
条件付きコンパイルの一般的な用途は、同じヘッダー ファイルが複数回インクルードされることを防止することです。C++ では、クラスは通常はヘッダー ファイルで定義されており、条件付きコンパイル コンストラクトを使用して多重定義を防止できます。次の例では、シンボリック定数 EXAMPLE_H が定義されているかどうかを確認します。定義されている場合は、ヘッダー ファイルは既にインクルードされており、再処理の必要はありません。定義されていない場合は、定数 EXAMPLE_H が定義されて、EXAMPLE_H が既に処理されていることが示されます。
#if !defined( EXAMPLE_H ) #define EXAMPLE_H class Example { ... }; #endif // !defined( EXAMPLE_H )