プログラミング原人の進化ログ

プログラミング原人の進化論

オレ プログラミング ベンキョウ スル。マナンダ コト カク。

【C/C++】ヘッダーファイルの#ifndef ~ #endifの意味

C++のヘッダーファイルを書く機会があって、#ifndefだの#endifだのが登場してなんぞこれとなったので、調べたことを簡単にまとめておきます。

目標

いつまでもおまじないで済ますわけにはいかないので、#ifndef~#endifが何者なのかを理解する。

#ifndef、#endifの意味するところ

これらの意味を理解するためには、プリプロセスというものを理解しておく必要があります。

プリプロセッサ命令

プリプロセスとは、ソースコードコンパイルする前に行う処理のこと。プリプロセスを行うプログラムをプリプロセッサと呼び、コンパイラが兼ねることが多いらしい。コンパイルの流れをまとめると、プリプロセッサソースコードの前処理をし、それをコンパイラに渡してコンパイルが行われるということになります。
でも、これだけではよくわからない、具体的に何をやっているんだろう?
調べてみたところ、

  • 条件付きコンパイル:条件によってコンパイル結果が異なる
  • エラー・警告の生成:これはよく見ますね
  • ソースコードの領域分け:可読性のためにコードをいくつかの部分に区切る

といったことをやってくれているのだそうです。
プリプロセッサ命令とはこのプリプロセスをプリプロセッサに指示するための命令のこと。#ifndef、#endifなんかはプリプロセッサ命令の1つですね。

重複定義を避ける

#ifndef _HOGE_H_
#define _HOGE_H_

// 処理

#endif

#ifndef~#endifはプリプロセッサ命令のうち、条件付きコンパイルを行うものに分類されます。
ある1つのヘッダファイルを複数のファイルがインクルードしてしまうと、そのヘッダファイルに書かれているクラスや関数は複数回定義されていることになります。
しかし、このようになんども宣言することが禁止されているため、#ifndef~#endifでソースコードを挟んであげることによって、すでに定義されている場合に再び定義されないようにすることができます。ifndefに続いて指定された記号定数(ここでは_HOGE_H_ )がすでに定義されているかどうかによって、重複定義の判定をします。#defineは記号定数を定義しています。
ところで、ifndefっていうのは"if not defined"の略なんでしょうかね。本当のところはわかりませんが。

まとめ

今回はソースコードの重複定義の回避について学びました。いつまでも「おまじない」として済ませておくわけにはいかないので...。
ところでなんで「おまじない」っていうんだろう。ただの定型文じゃなくて、意味がわからず使っているっていう意味なんだろうか。あるいは、「おまじない」から漂うダサさから脱却しようと初心者が勉強に励むことを見越しているのだろうか?もしそうだとしたら考えた人はかなりの策士だなぁ。