まず、最も良く使われるものが #ifdef
文である。これは以下の
ように使う。
#define DEBUG ... #ifdef DEBUG printf("Debug: hensuu = %d\n", hensuu); #endif |
つまり、DEBUG
というマクロが定義されていたならば、
#ifdef
と #endif
の間の行が有効になりますが、
もし最初の行の#define DEBUG
がなければ、この
#ifdef
と #endif
で囲まれた行はないものとして
プリプロセッサに処理され、結果として printf文はコンパイラ
から見ると元から無かったようになります。このように、プログラム
の動作を検証している間は色々な変数の状態などを見るために、
それらの値を出力したいが、完成したらそれを削除するために
しばしばこの使い方が好まれます。
もう一つのこの #ifdef
文の使い方は、インクルードファイル
にあります。
例えば、外部変数をインクルードファイルで宣言し、それらを他の
モジュールから参照したい場合(つまりは extern 宣言)したいような
場合に、共通の一つのインクルードファイルを使いたいとしましょう。
これは次のようにして可能になります。
#ifdef THIS_MODULE int common; /* このモジュールで使う */ #else extern int common; /* 他のモジュールから見る*/ #endif |
そして、common
変数を主に使いたいモジュールの先頭で、
#define THIS_MODULE
を定義して、このファイルをインクルード
しておけば良い訳です。他のモジュールでは、何の定義もなしに
ただインクルードするだけで外部変数の参照として common
変数
が利用可能になります(勿論、外部変数の使用は極力止めるべきですが)。
インクルードファイルにおけるマクロの利用には別のタイプもあります。
例えば、あるインクルードファイルが二重に取り込まれないように
するにはどうすれば良いでしょうか?勿論、二重に取り込まないように
注意すべきですが、それがどうしても難しい場合もあります。
このような場合には、#define
を使って目印を付けるという
方法が有効です。
#ifndef MY_INCLUDE #define MY_INCLUDE ... /* インクルードファイルの記述をここに書く */ #endif |
ここで、#ifndef
は ifdef
の逆で、マクロが未定義
の場合に真となります。これによって、最初にこのインクルードファイル
を取り込んだ時には、マクロ定義 MY_INCLUDE
は定義されて
いないので、#ifndef
が真になります。その結果、#endif
までの文が取り込まれ、同時にその中でマクロ定義 MY_INCLUDE
が定義されているので、2回目にこのインクルードファイルが取り込まれ
た時には、MY_INCLUDE
が定義されているために、
#ifndef
と #endif
の間の行は有効にはならない訳です。
この例の逆の使い方も stdio.h に見られます。
/* stdio.h の一部 */ #ifdef _BSD_SIZE_T_ typedef _BSD_SIZE_T_ size_t; #undef _BSD_SIZE_T_ #endif |
ここで使われている undef
は一度定義したものを無定義に
戻すマクロ命令です。つまり、もし _BSD_SIZE_T_
という
マクロ定義がされていたならば、それを size_t
という名前
の新しい型として再度型定義し、先の _BSD_SIZE_T_
を
無効にします(つまりは、二度目はこの typedef は起きない)。
実際には、_BSD_SIZE_T_
は machine/ansi.h
の内部で
定義されており、
#define _BSD_SIZE_T_ unsigned int |
となっています。最終的には、最初の一度だけ
typedef unsigned int size_t; |
が型定義されている訳です(これは BSD のコードの場合)。
その他の #ifdef
の使い方はある種のコメント文に使う方法
です。
例えば、次のようなコードがあり、それらをコメントアウトする事を
考えましょう。
/* code 1 */ a = hogehoge(b); /* ここで受け取ってほげほげ */ ... /* end of code 1 */ |
これらの行を単純にコメントにするとエラーになります。
/* /* code 1 */ a = hogehoge(b); /* ここで受け取ってほげほげ */ ... /* end of code 1 */ */ |
何故ならば、C言語ではコメントアウトの入れ子は出来ないからです。
そこで、次のようにします。
#ifdef OLD_CODE1 /* code 1 */ a = hogehoge(b); /* ここで受け取ってほげほげ */ ... /* end of code 1 */ #endif |
これで、OLD_CODE1
をマクロ定義しない限り、この部分の
プログラムはプリプロセッサによって削除される訳です。