プログラミング言語 C

(#define で 取り込む) 前処理そのものを 制御するには、その間に 評価を行なう (# で始まる) 条件文を 使うことで 可能となる。この時 評価される 条件の値に 応じて、コンパイル時に コードが 選択され 取り込まれる。

まず #if 行で 式を評価する。この式は 定数整数式なので sizeof 演算子、型変換 (キャスト)、enum 定数を 含んではならない。

この式の値が 0 以外 (= 真) である場合にのみ、後続する #endif 行までの コードが 取り込まれる。条件式に #elif と #else とが 含まれる場合も、同様に それぞれの値によって 評価が 行なわれる。

例えば、あるヘッダファイルを「確実に 一度だけ」取り込むためには、そのヘッダファイルの 内容を 次のように 条件式で 囲むとよい。

#if !defined(HEADER)
#define HEADER
/* header.h ファイルの 内容をここに置く */
#endif

defined 演算子は、(カッコの中の) NAME が 定義されていれば 1、そうでなければ 0 を 返す。

最初に header.h ファイルを 取り込んだ時点で、HEADER という NAME が 定義される。

次に、同じファイルを 取り込もうとすると、すでに この NAME は 定義されている (ので defined 演算子の値は 1 となり さらに ! 演算子により 最終的には 0 が 返ることになる)。(その結果) #endif 行までの コードは スキップされる。

この方法で 系統的に (条件文を) 記述すると、各 OS の システム毎に 依存するヘッダを (自動的に) 選択させることができる。こうすれば、ユーザは システムへの依存性を いちいち 気にかける必要性が なくなる。

次の 一連のテストでは SYSTEM という NAME を 使って、どのヘッダファイルを 選択するかを 決定している。

#if SYSTEM == SYSV
#define HEADER "sysv.h"
#elif SYSTEM == BSD
#define HEADER "bsd.h"
#elif SYSTEM == MSDOS
#define HEADER "msdos.h"
#else
#define HEADER "default.h"
#endif
#define HEADER

#ifdef および #ifndef を 使った 条件文では、NAME が 定義済みか どうかを テストすることが 可能となる。

例えば、#ifndef 文を 用いると、最初の例を (defined 演算子を 使わずに) 次のように 書くことができる。

#ifndef HEADER
#define HEADER
/* header.h ファイルの内容を ここに置く */
#endif

(p111-112)

(追記) #ifdef を #ifendef に 訂正 (05/10/13)