英語で読む

次の方法で共有


#define ディレクティブ (C/C++)

#define は、識別子またはパラメーター化された識別子とトークン文字列との関連付けである、マクロを作成します。 マクロが定義されると、コンパイラはそれ以降にソース ファイル内に識別子が見つかるたびに、トークン文字列に置き換えることができます。

構文

#define identifier token-stringopt
#define identifier ( identifieropt, ... , identifieropt )) token-stringopt

解説

#define ディレクティブにより、コンパイラは、token-string をソース ファイル内で identifier が出現するたびに置き換えます。 identifier は、それがトークンを形成する場合のみ、置き換えられます。 つまり、識別子がコメント、文字列、または長い識別子の一部として出現する場合、identifier は置き換えられません。 詳細については、Tokens に関するページを参照してください。

token-string 引数は、キーワード、定数、完全なステートメントなどの一連のトークンで構成されます。 1 つ以上の空白文字で、token-stringidentifier から分離する必要があります。 この空白は、置き換えられるテキストの一部とは見なされません。最後のトークンのテキストに続く空白も同様です。

#definetoken-string がない場合、identifier の出現をソース ファイルから削除します。 identifier を定義したまま、#if defined ディレクティブと #ifdef ディレクティブを使用してテストできます。

2 番目の構文形式は、パラメーターを受け取る関数に似たマクロを定義します。 この形式では、かっこで囲んだパラメーターのリストを使用できます (省略可能)。 このマクロが定義されると、それ以降の identifier( identifieropt, ..., の発生のたびに、identifieropt ) は、正式なパラメーターの代わりに実引数を持つ token-string 引数のバージョンに置き換わります。

仮パラメーターの名前は token-string に含まれ、実際の値が代入される場所を示します。 各パラメーター名は、token-string 内に任意の順序で複数回含めることができます。 呼び出しにある引数の数は、マクロ定義にあるパラメーターの数に一致する必要があります。 かっこを多めに使用することで、複雑な実引数が正しく解釈されるようにできます。

リスト内で仮パラメーターはコンマで区切ります。 リストの各名前は一意である必要があり、リストはかっこで囲む必要があります。 空白を identifier と左かっこの間に挿入することはできません。 複数のソース行にまたがる長いディレクティブには行の連結を使用します (改行文字の直前に円記号 (\) を挿入します)。 仮パラメーター名のスコープは、token-string で終了する新しい行まで拡張されます。

マクロが 2 番目の構文形式で定義されると、それ以降の引数リストまでのテキスト インスタンスがマクロの呼び出しを示します。 ソース ファイル内の identifier のインスタンスに続く実引数は、マクロ定義内の対応する仮パラメーターと対になります。 文字列化演算子 (#)、文字定数化演算子 (#@)、またはトークン連結演算子 (##) が前置されていないか、## 演算子が後置されていない token-string の各仮パラメーターは、対応する実引数に置き換えられます。 ディレクティブが仮パラメーターを置き換える前に、実引数内のすべてのマクロが展開されます (演算子については「プリプロセッサ演算子」を参照)。

引数を受け取るマクロの次の例では、#define 構文の 2 番目の形式を示しています。

// Macro to define cursor lines
#define CURSOR(top, bottom) (((top) << 8) | (bottom))

// Macro to get a random integer with a specified range
#define getrandom(min, max) \
    ((rand()%(int)(((max) + 1)-(min)))+ (min))

副作用のある引数が原因で、マクロが予期しない結果を生成することがあります。 同じ仮パラメーターが token-string に複数回含まれている場合があります。 その仮パラメーターが副作用のある式と置き換えられると、その式は、その副作用と共に、複数回評価される場合があります (「トークン連結演算子 (##)」の例を参照)。

#undef ディレクティブは、識別子のプリプロセッサ定義を未定義の状態にします。 詳細については、「#undef ディレクティブ」を参照してください。

定義されているマクロの名前が token-string に見つかった場合 (別のマクロの展開の結果であっても)、この名前は展開されません。

同じ名前のマクロの 2 番目の #define は、2 番目のトークン シーケンスが最初のものと同じでなければ、警告を生成します。

Microsoft 固有の仕様

Microsoft C/C++ では、新しい定義が元の定義と構文的に同一の場合、マクロを再定義できます。 つまり、2 つの定義に異なるパラメーター名を付けることができます。 この動作は、2 つの定義が語彙的に同一である必要がある ANSI C とは異なります。

たとえば、次の 2 つのマクロは、パラメーター名を除いて同一です。 ANSI C ではこのような再定義はできませんが、Microsoft C/C++ ではエラーなしでコンパイルされます。

#define multiply( f1, f2 ) ( f1 * f2 )
#define multiply( a1, a2 ) ( a1 * a2 )

一方、次の 2 つのマクロは同一ではなく、Microsoft C/C++ で警告が生成されます。

#define multiply( f1, f2 ) ( f1 * f2 )
#define multiply( a1, a2 ) ( b1 * b2 )

Microsoft 固有の仕様はここまで

#define ディレクティブの例を次に示します。

#define WIDTH       80
#define LENGTH      ( WIDTH + 10 )

最初のステートメントは識別子 WIDTH を整数定数 80 として定義し、LENGTH と整数定数 10 に基づき WIDTH を定義します。 LENGTH は見つかるたびに (WIDTH + 10) に置き換えられます。 次に、WIDTH + 10 は見つかるたびに式 (80 + 10) に置き換えられます。 WIDTH + 10 を囲むかっこは、次のようなステートメントの解釈を制御するため重要です。

var = LENGTH * 20;

プロプロセス段階が終了すると、ステートメントは次のようになります。

var = ( 80 + 10 ) * 20;

1800 に評価されます。 かっこがない場合、結果は次のようになります。

var = 80 + 10 * 20;

280 に評価されます。

Microsoft 固有の仕様

/D コンパイラ オプションを使用したマクロおよび定数の定義は、ファイルの先頭に #define プリプロセス ディレクティブを使用する場合と同じ結果になります。 /D オプションを使用して最大 30 個のマクロを定義できます。

Microsoft 固有の仕様はここまで

関連項目

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