第18章 if...2

 前回は #if ディレクティブをとりあえず使ってみました。今回は、その詳しい書式と、よく使われる例について話したいと思います。


 では、今回の要点です。


 では、いってみましょう。


 前回、#if を使いました。しかし、第1部第70章では #ifndef というのを使っていました。定義されているかの判定はよく使われるので、それ用の命令が用意されているのです。

 定義されているかの判定に使われるのは、#ifdef, #ifndef の2種類です。それぞれ、if defined(もし定義されていれば)、if not defined(もし定義されていなければ)の略です。

 そして、if 文に else があるように、#if ディレクティブには #else ディレクティブがあります。

 また、else if に対しては、#elif ディレクティブを使います。#elifdef などはないので、#elif defined(<名前>) とする必要があります。

 まとめると、例えば次のようになるわけです。

#ifdef _WIN
#define RET_CODE "\r\n"
#elif defined(_MAC)
#define RET_CODE "\r"
#else
#define RET_CODE "\n"
#endif

 先ず、_WIN が定義されていれば RET_CODE は "\r\n" で定義されます。そして、_WIN が定義されていないが、_MAC が定義されているときは、RET_CODE は "\r" で定義されます。そして、_WIN も _MAC も定義されていないときは、"\n" で定義されます。


 #if ディレクティブの評価式で使えるのは、プログラムをコンパイルする前から値を判断できるデータだけです。#if 文の動作を考えると、当然のことといえます。例えば、マクロとか、即値(生の数値)とかがそうです。

 使える演算子は、C/C++のものとほとんど変わりません。使えない演算子は new, delete, sizeof のようなものくらいです。

 まとめると、例えば次のようになるわけです。

define VALUE 100

#if !(VALUE % 5 == 0 && VALUE > 0)
// #error ディレクティブは、強制的にエラーを出す命令です
#error VALUE must be a multiple of 5 and more than 0
#endif

 先ず、マクロ VALUE を定義しています。この数が「正の5の倍数でなくてはならない」としたいと思います。

 ということは、VALUE が正の5の倍数でない時にはエラーを出すようにすればいいのです。#if ディレクティブでその評価を行い、そして正の5の倍数にならないときは #error ディレクティブでエラーを出します。

 このようにすれば、VALUE の初期化ミスを防ぐことができます。


 #if ディレクティブは、前回やったように、デバッグ時にのみ動作するコード、またはその逆のコードを書くために使うことがよくあります。そのため、VC++ではデバッグ時には _DEBUG というマクロが自動的に定義されます。他のツールであっても、似たようなマクロが定義されているかもしれません。

 実は、このマクロはプロジェクトの設定内で定義されています。第1部第70章でやったようにプロジェクトの設定を開き、「C/C++」→「一般」カテゴリ→「プリプロセッサの定義」を見てみて下さい。_DEBUG と書いてあると思います。

 で、デバッグを終了し、いざ本ビルドを行うというときは、メニューの「ビルド」から、「アクティブな構成の設定」を選び、Win32 Release を選択します。もしくは、ツールバーの Win32 Debug と書いてあるコンボボックスからも選択できます。こうすると、プロジェクトの設定が変わり、_DEBUG の定義されていない状態になります。

 このように、VC++ではプロジェクトの設定を数種類保存でき、簡単に切り替えられるようになっています。


 #if ディレクティブを使えば、デバッグ時にしか有効にならないコードを作ることもできます。その逆もできます。

#ifdef _DEBUG
void Func(int a, int b);
#define NOMORE  default: exit(1);
#else
#define Func(a, b)
#define NOMORE
#endif

 _DEBUG が定義されていないときは、Func の呼び出しは消えて、空文になってしまいます。デバッグ時にしか呼び出せないわけです。NOMORE も同じですね。

 他にも、環境によって定義を変えることもできます。上で話した RET_CODE がそうです。_WIN は Windows 環境用、_MAC は Macintosh 環境用であることを表しています。で、それ以外用のが #else 以降で定義されています。

 このように、#if ディレクティブを使うと、状況に合わせた柔軟なプログラムを書けるようになるのです。

 ただ、#if ディレクティブを関数の中に頻繁に書いていると、非常に読みにくくなってしまいます。やむを得ない場合でも、なるべく見づらくならないような工夫をこらすようにしましょう。

 例としては、上でやったデバッグ時にしか動作しないコード(またはその逆)がそうです。Func を呼ぶたびに #if ディレクティブを使うよりも、Func が消える上のコードを書いておく方がいいですね。


 では、今回の要点です。


 それでは、次回まで。


第17章 if... | 第19章 組み込みマクロ

Last update was done on 2001.5.28

この講座の著作権はロベールが保有しています