next up previous contents
Next: 16.2.2 #if 文 Up: 16.2 プリプロセッサにおける条件文 Previous: 16.2 プリプロセッサにおける条件文

16.2.1 #ifdef 文

まず、最も良く使われるものが #ifdef 文である。これは以下の ように使う。

    #define DEBUG
    ...
    #ifdef DEBUG
           cout << "Debug: hensuu = " << hensuu << endl;
    #endif

つまり、DEBUG というマクロが定義されていたならば、 #ifdef#endif の間の行が有効になりますが、 もし最初の行の#define DEBUG がなければ、この #ifdef#endif で囲まれた行はないものとして プリプロセッサに処理され、結果として cout 文はコンパイラ から見ると元から無かったようになります。このように、プログラム の動作を検証している間は色々な変数の状態などを見るために、 それらの値を出力したいが、完成したらそれを削除するために しばしばこの使い方が好まれます。

もう一つのこの #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

ここで、#ifndefifdef の逆で、マクロが未定義 の場合に真となります。これによって、最初にこのインクルードファイル を取り込んだ時には、マクロ定義 MY_INCLUDE は定義されて いないので、#ifndef が真になります。その結果、#endif までの文が取り込まれ、同時にその中でマクロ定義 MY_INCLUDE が定義されているので、2回目にこのインクルードファイルが取り込まれ た時には、MY_INCLUDE が定義されているために、 #ifndef#endif の間の行は有効にはならない訳です。

この例の逆の使い方も stdio.h(これはC のヘッダファイルです) に見られます。

    /* 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 をマクロ定義しない限り、この部分の プログラムはプリプロセッサによって削除される訳です。



Noriyo Kanayama