まず、最も良く使われるものが #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 をマクロ定義しない限り、この部分の
プログラムはプリプロセッサによって削除される訳です。