#ifndef C にガードを含める
この記事では、C 言語で #ifndef
インクルードガードを使用する方法を複数紹介します。
C 言語でヘッダファイルの多重インクルードを防ぐために #ifndef
インクルードガードを使用する
C 言語のヘッダファイルは、同じ名前のソースファイルに実装されている関数のインタフェースを定義するために使用されます。インターフェースには、通常、関数のプロトタイプ、公開されているデータ構造の定義、その他の雑多なものが含まれています。
ヘッダファイルがソースファイルに複数回含まれていると、コンパイラエラーが発生する可能性があることに注意してください。通常、これはラッパーの #ifndef
と呼ばれる #ifndef
プリプロセッサ指令で防ぐことができます。以下の例では、ヘッダファイルの内容を、#ifndef MY_GUARD
ディレクティブが始点、#endif
が終点となるような構造で囲んでいます。ifndef
ディレクティブは MY_GUARD
マクロが定義されているかどうかをチェックし、定義されていなければ次のディレクティブで定義します。ユーザが同じヘッダを 2 回目にインクルードした場合、ifndef
ディレクティブは false を評価し、#endif
ディレクティブの前のコードを無視します。その結果、コンパイラはこのヘッダファイルからコードのコピーを 1つだけ取得して翻訳に成功します。
#include <stdio.h>
#ifndef MY_GUARD
#define MY_GUARD 1
#define PER(D) #D
#define JOIN(A, B) (A##B)
#define JOINX(A, B) JOIN(A, B)
int power(int base, int n) {
int p = base;
for (size_t i = 0; i < n; i++) {
p *= base;
}
return p;
}
#endif
同じ結果を得るための別の方法として、#pragma once
ディレクティブをヘッダファイルに含める方法もあります。プリプロセッサはこれらのヘッダファイルを一度だけスキャンし、二度と読み込まれないことを保証します。以下の方法の欠点は、異なるプリプロセッサ間での移植性が低いということです。
#include <stdio.h>
#pragma once
#define PER(D) #D
#define JOIN(A, B) (A##B)
#define JOINX(A, B) JOIN(A, B)
int power(int base, int n) {
int p = base;
for (size_t i = 0; i < n; i++) {
p *= base;
}
return p;
}
マクロが C 言語で複数回定義されないようにするために ifndef
ディレクティブを使用する
あるいは、ifndef
ディレクティブを使って、与えられたマクロ式がすでに定義されているかどうかをチェックすることもできます。式が定義されていない場合は、次の #define
ディレクティブがそれに応じて処理されます。ifndef
と #endif
の間の行はマクロの定義を 1 行だけにして、条件が false の場合は与えられたマクロの定義だけをスキップします。
#include <stdio.h>
#include <stdlib.h>
#define PER(D) #D
#ifndef DLEVEL
#define DLEVEL 6
#endif
int main() {
for (int j = 0; j < DLEVEL; ++j) {
printf("%s\n", PER(stringify this));
}
exit(EXIT_SUCCESS);
}