Caution
お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。
#ifdef / #ifndef / #if / #endif
条件付きコンパイルは、マクロの定義状態や値に応じてソースコードの特定部分をコンパイルするかしないかを制御します。複数のプラットフォーム対応やデバッグコードの切り替え、ヘッダファイルの二重読み込み防止などに使われます。
構文
// マクロが定義されている場合にコンパイルします。
#ifdef マクロ名
コード
#endif
// マクロが定義されていない場合にコンパイルします。
#ifndef マクロ名
コード
#endif
// #else と組み合わせた条件分岐です。
#ifdef マクロ名
マクロが定義されている場合のコード
#else
マクロが定義されていない場合のコード
#endif
// マクロの値で条件を評価します。
#if 定数式
コード
#elif 定数式
コード
#else
コード
#endif
// ヘッダガード(二重インクルード防止のイディオム)です。
#ifndef ヘッダ名_H
#define ヘッダ名_H
// ヘッダの内容
#endif
条件付きコンパイル命令一覧
| 命令 | 概要 |
|---|---|
| #ifdef | 指定したマクロが定義されていればブロックをコンパイルします。 |
| #ifndef | 指定したマクロが定義されていなければブロックをコンパイルします。ヘッダガードに使われます。 |
| #if | 定数式が0以外(真)ならブロックをコンパイルします。マクロの値で分岐できます。 |
| #elif | #if / #ifdef / #ifndef に続けて別の条件を追加します。 |
| #else | 直前の条件が偽のときのブロックを定義します。 |
| #endif | 条件ブロックを終了します。 |
| defined(マクロ名) | #if の中でマクロが定義済みかどうかを判定する演算子です。 |
サンプルコード
#include <stdio.h>
// デバッグモードのマクロを定義します(コンパイル時に -DDEBUG で渡すこともできます)。
#define DEBUG
// OSごとのコンパイル分岐です。
#if defined(_WIN32) || defined(_WIN64)
#define PLATFORM "Windows"
#elif defined(__linux__)
#define PLATFORM "Linux"
#elif defined(__APPLE__)
#define PLATFORM "macOS"
#else
#define PLATFORM "Unknown"
#endif
// デバッグログマクロです(DEBUG が定義されているときだけ動作します)。
#ifdef DEBUG
#define LOG(msg) printf("[DEBUG] %s\n", msg)
#else
#define LOG(msg) // 何もしません(リリースビルドでは消えます)。
#endif
int main(void) {
printf("プラットフォーム: %s\n", PLATFORM);
LOG("プログラムを開始します。"); // DEBUG が定義されているので出力されます。
int x = 42;
#ifdef DEBUG
// デバッグ時だけ変数の値を確認します。
printf("[DEBUG] x = %d\n", x);
#endif
// #if で定数値による分岐を行います。
#define VERSION 2
#if VERSION >= 2
printf("バージョン2以上の機能を使います。\n");
#elif VERSION == 1
printf("バージョン1の機能を使います。\n");
#else
printf("未知のバージョンです。\n");
#endif
return 0;
}
概要
ヘッダファイルには必ずヘッダガードを付けてください。同じヘッダが複数回インクルードされると型や関数の多重定義エラーが発生します。ヘッダガードのマクロ名には大文字・アンダースコアでファイル名を表す名前(例:『MYHEADER_H』)を使い、他のマクロと衝突しないようにしてください。
コンパイラによっては『#pragma once』という非標準の命令でヘッダガードを簡潔に書けますが、C言語の規格ではないため、移植性を重視する場合は従来の『#ifndef』パターンを使ってください。
『#pragma』については『#pragma / #error / #warning』を、マクロ定義の基本については『#include / #define(定数)』を参照してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。