質問: 参考書なので、これの使い方について理解したつもりですが、勉強のために長いコードを拝見すると、ヘッダーファイルや、メインプログラムの先頭に、#ifdef #endif elif や else など様々なコマンドがあり、なかなか理解することができません。 申し訳ないですが、簡単に説明していただくことはできますでしょうか。下記のコードはネットで見つけたサンプルです。 参考書で理解したつもりが、下記のコードを見てぜんぜん分からなくなり、混乱してしまいました。 ### ソースコード ``` #define SLASH '\\' #else #define SLASH '/' #endif 他 #ifdef LIBTK_EXPORTS # if defined(__lint) # define TKEXPORT __export(TK) # define TKGLOBAL extern __global(TK) # define TKPRIVATE extern __private(TK) # elif defined(_WIN32) # define TKEXPORT __declspec(dllexport) # define TKGLOBAL extern __declspec(dllexport) # define TKPRIVATE extern # else # define TKEXPORT # define TKGLOBAL extern # define TKPRIVATE extern # endif #else # if defined(__lint) # define TKEXPORT __export(TK) # define TKGLOBAL extern __global(TK) # elif defined(_WIN32) && !defined(WNT_STATIC_LINK) # define TKEXPORT __declspec(dllimport) # define TKGLOBAL extern __declspec(dllimport) # else # define TKEXPORT # define TKGLOBAL extern # endif #endif ```
回答: `#ifdef`〜`#endif`の使われるパターンはだいたい次の三つに分かれます。 1. インクルードガード) ヘッダファイルが二重に読み込まれるのを防ぐために使います。ただ、最近は同じ事を実現可能な`#pragma once`(非標準の機能です)に対応したコンパイラがほとんどのため、想定しているコンパイラが限定されている場合は`#pragma once`を使うことが多いようです(特にVC++向けのプログラムは)。 2. 環境(OSやコンパイラなど)の違いを吸収するため 例えば、Windowsではフォルダの区切りは`\`ですが、UNIX(Mac含む)/Linuxでは`/`です。このようにOSやコンパイラによって違いが出てくるときがあり、それぞれ別の処理が必要になる場合があります。OSやコンパイラによって定義済みのマクロが異なる(たとえば、Windowsだと_WIN32が定義されるが、それ以外ではされない)ため、それを`#ifdef`でチェックすることで、Windowsのみでの動作、UNIX(Mac含む)/Linuxのみでの動作と分けることが可能になります。この分岐はコンパイル時に行われるため、実行時に分岐の処理分遅くなると言うこともありません。 3. 機能のON/OFF 使用者が少ない非常にマイナーな機能やまだバグが残っているかも知れない実験的な機能は不要であれば無効にできた方がいいでしょう。また、デバッグの有効/無効でログの出方等も調整したいと思うでしょう。そこでC/C++ではコンパイル時に定義済みのマクロを指定できるようになっています。例えばgccで`-DDEBUG`とオプションをつけると`#define DEBUG`が一番最初に書かれた場合と同じ効果が得られます。それを利用して、`DEBUG`が定義済みの時だけ、詳細メッセージを出すと言ったことができます。この分岐もコンパイル時に行われるため、実行時の処理速度に影響を与えません。