14 Mar 2014, 12:05

C言語の二重インクルード(多重インクルード)防止について

C言語のヘッダファイルでおまじないのように書いているコレ。

#ifndef  _FOO_H_
#define  _FOO_H_

#endif

インクルードガードという。いったいなんなのか調べた。

無限ループ防止

互いのヘッダファイルをインクルードしあうと、コンパイル時に無限ループに陥る。

foo.h

#include "bar.h"

bar.h

#include "foo.h"

実行結果

<div class="outline-text-3" id="text-1-1">
  <div class="org-src-container">
    <pre class="src src-language">  $gcc foo.c bar.c
 ... 
     from foo.h:1,
     from bar.h:4,
     from foo.h:1,
     from bar.h:4,
     from foo.h:1,
     from bar.h:4,
     from foo.h:1,
     from bar.h:4,
     from foo.h:1,
     from bar.h:4,
     from foo.h:1,
     from foo.c:2:

foo.h:1:17: error: #include nested too deeply #include “bar.h”

構造体のコンパイルエラー

一つの.hにある構造体を二つの.cでインクルードすると、コンパイルエラーが発生する仕様。

foo.h

struct test{
  int test;
};

bar.c / foo.c

#include "foo.h"

実行結果

<div class="outline-text-3" id="text-2-1">
  <pre><code>

% gcc bar.c foo.c In file included from bar.c:3:0: foo.h:2:8: error: redefinition of ‘struct test’ struct test{ ^ In file included from bar.h:4:0, from bar.c:2: foo.h:2:8: note: originally defined here struct test{

progma onceについて

インクルードガードを実現するためのコンパイラの仕組みに、#pragma onceというのがある。

ヘッダファイルの先頭に以下を記述するだけ。

#pragma once

#ifndefは別の機能をたまたま応用にしているに過ぎないが、 #pragma onceは機能としてあるので直接的。