c-lang:マクロ定義
マクロ定義(#define文)
「便利な」マクロというようなものを求めると、ただの置換えというよりも、コーディングテクニックや、トリックを隠したり、分かりやすくするための使命を帯びたものになる。 気のきいたマクロが書けるようになるのが、C使いの必須条件である。(たぶん) マクロの機能は、単に文字列を置換するだけである。
マクロでは、スペースを空けることはできない。
プリプロセッサのディレクティブは、通常、行末で終了する。この点が、コロン(;)が文の終了を表すC本体と異なる。
複数行に渡って、マクロ定義する場合には、前の行の行末に\をつける。
#define で定義する定数式は必ずカッコで囲む。
引数を取るマクロの引数は必ずカッコで囲む。
実際の値が重要でない場合、defineによる定数宣言ではなく、enumを用いるべきである。
定数宣言には、定数の意味がわかるようなコメントを記述する。
乱用の戒め
マクロは強力なので、注意して使う。
単純マクロ
code:cpp
プリプロセッサは、定義されたマクロ名を見つけると、それを元の記号列に置き換える。
引数付きマクロ
code:cpp
「SQUARE」と「(」の間にスペースをいれてはならない。
マクロの副作用
code:cpp
と定義した場合、「SQUARE(5)」は、「5*5」に展開され、値は25になる。
しかし、「SQUARE(4+1)」は「4+1*4+1」に展開され、値は 9となり、意図した動作をしない。 code:cpp
と定義すれば、 「SQUARE(4+1)」は「(4+1)*(4+1)」に展開され、値は 25 となり、意図した動作をする。
code:cpp
#define sqrt(x) ((x<0)?sqrt(-x):sqrt(x)) 古いCプリプロセッサは、こうした回帰を検出せず、システムエラーが起きるまで展開を止めようとしない。
複数行にまたがるマクロ
\で終わる行はつぎの行と併合される。
定義済マクロ
ANSI では、特別なマクロを定義している。
__LINE__
現在のソースプログラム行の行番号
__FILE__
現在のソースファイル名
__DATE__
コンパイル日
__TIME__
コンパイル時刻
__STDC__
コンパイラがANSI準拠製品の場合のみ十進定数の1
いろいろなマクロ
デバッグライトのマクロ
code:cpp
#define DbgPrt2(f,a,b) fprintf(stderr,f,a,b) ダミー関数を作るマクロ
code:cpp
#define MakeDummyFunction(type,fn)\ type fn() \
{ \
fprintf(stderr,"fn() is not supported\n");\
}
関数のようなマクロ
code:cpp
#define swap(a, b) do { int tmp = a; a = b; b = tmp; } while(0) whileの評価は常に偽なので、doステートメントの内部は1回だけ実行されることになる。
さらに do { ... } while(0)ステートメントは1つの文としてみなされるので、if節で裸で使っても問題は発生しない。