#ifndef C にガードを含める

胡金庫 2023年10月12日
  1. C 言語でヘッダファイルの多重インクルードを防ぐために #ifndef インクルードガードを使用する
  2. マクロが C 言語で複数回定義されないようにするために ifndef ディレクティブを使用する
#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);
}
著者: 胡金庫
胡金庫 avatar 胡金庫 avatar

DelftStack.comの創設者です。Jinku はロボティクスと自動車産業で8年以上働いています。自動テスト、リモートサーバーからのデータ収集、耐久テストからのレポート作成が必要となったとき、彼はコーディングスキルを磨きました。彼は電気/電子工学のバックグラウンドを持っていますが、組み込みエレクトロニクス、組み込みプログラミング、フロントエンド/バックエンドプログラミングへの関心を広げています。

LinkedIn Facebook