マクロ代入( #define )

プリプロセッサディレクティブはコンパイルする前にソースコードを前処理するためにコンパイラによって使用されます。ディレクティブは常に#で始まります。したがって、コンパイラは変数名、関数名などでのこのシンボルの使用を禁止します。

各ディレクティブはエントリごとに指定されます。1つのエントリで複数のディレクティブを使用することはできません。ディレクティブエントリが大きすぎる場合は、 '\' 記号を使用して複数の行に分割します。この場合、次の行はディレクティブエントリの続きと見なされます。

#define ディレクティブは、定数にニーモニック名を割り当てるために使用することが出来ます。#define には 2 つの形式があります。

#define 識別子式                           // パラメータなしの形式
#define 識別子 (パラメータ1,... パラメータ8) 式   // パラメトリック形式

#define ディレクティブは後に続くソーステキストで識別子があった場合その全てにを代入します。代入は識別子が独立したトークンである場合にのみ行わます。代入は識別子がコメントの一部、文字列の一部、または他の長い識別子の一部である場合には行われません。

定数識別子は、変数名と同じ規則によって扱われます。値は任意の型のものとすることが出来ます。

#define ABC               100
#define PI                3.14
#define COMPANY_NAME     "MetaQuotes Software Corp."
...
void ShowCopyright()
 {
  Print("Copyright  2001-2009, ",COMPANY_NAME);
  Print("https://www.metaquotes.net");
 }

はキーワード、定数、定数及び非定数式などのいくつかのトークンで構成されます。は行の終わりで終了し、次の行に続くことは出来ません。

例:

#define TWO        2
#define THREE      3
#define INCOMPLETE TWO+THREE
#define COMPLETE  (TWO+THREE)
void OnStart()
 {
  Print("2 + 3*2 = ",INCOMPLETE*2);
  Print("(2 + 3)*2 = ",COMPLETE*2);
 }
// 結果
// 2 + 3*2 = 8
// (2 + 3)*2 = 10

 

パラメトリック形式の #define

パラメトリック形式の場合、後続する識別子の全てが実際のパラメータを考慮して代入されます。例えば、

// 2 つのパラメータ a と b を使用する例
#define A 2+3
#define B 5-1
#define MUL(a, b) ((a)*(b))
 
double c=MUL(A,B);
Print("c=",c);
/*
double c=MUL(A,B); の式は
double c=((2+3)*(5-1)); と同じです。
*/
// 結果
// c=20

見つけにくい非明白なエラーを防ぐために、式の中でパラメータを使用する際にはパラメータを括弧で囲むようにしてください。ブラケットを使用せずにコードを書き換えると、結果が異なります。

// 2 つのパラメータ a と b を使用する例
#define A 2+3
#define B 5-1
#define MUL(a, b) a*b
 
double c=MUL(A,B);
Print("c=",c);
/*
double c=MUL(A,B); の式は
double c=2+3*5-1; と同じです。
*/
// 結果
// c=16

パラメトリック形式では、最大で 8 つのパラメータが使用可能です。

// パラメトリック形式の正しい使い方
#define LOG(text) Print(__FILE__,"(",__LINE__,") :",text)         // パラメータは「text」の 1 つ
 
// パラメトリック形式の不正な使い方        
#define WRONG_DEF(p1, p2, p3, p4, p5, p6, p7, p8, p9)   p1+p2+p3+p4 // パラメータが p1 から p9 の 8 つ以上

 

#undef ディレクティブ

#undef は、前に定義されたマクロ代入の宣言を解除します。

例:

#define MACRO
 
void func1()
 {
#ifdef MACRO
  Print("MACRO is defined in ",__FUNCTION__);  
#else
  Print("MACRO is not defined in ",__FUNCTION__);
#endif
 }
 
#undef MACRO
 
void func2()
 {
#ifdef MACRO
  Print("MACRO is defined in ",__FUNCTION__);
#else
  Print("MACRO is not defined in ",__FUNCTION__);
#endif
 }
 
void OnStart()
 {
  func1();
  func2();
 }
 
/* 結果:
MACRO is defined in func1
MACRO is not defined in func2
*/

参照

識別子文字定数