インクルードガードに関する誤解とその理由の考察

何事もそうですが、よく理解できていない初心者というのは、想像を超えた発想をするものです。最近は、根本的な部分の理解をおろそかにして、安易に結果だけを得ようとする、あるいは教えようとすることが多いこともあり、なおさらその傾向が強いように思います。

今回取り上げるのは、ヘッダファイルにインクルードガードを設置すれば、プログラム全体でただ一度だけそのヘッダファイルの内容が有効になるという誤解です。具体的には、次のようなケースです。

/* foo.h */
#ifndef FOO_H
#define FOO_H
 
int foo;
 
#endif /* FOO_H */
/* main.c */
#include "foo.h"
 
void sub(void);
 
int main(void)
{
  foo = 123;
  sub();
  return 0;
}
/* sub.c */
#include "foo.h"
#include <stdio.h>
 
void sub(void)
{
  printf("%d\n", foo);
}

処理系によってはこれでもうまくいってしまうのですが、原則としてこのようなコードには問題があります。main.cとsub.cの両方からfoo.hをインクルードしているので、変数fooの定義が重複してしまうからです。少し経験を積んだC/C++プログラマであれば、常識的なことです。

ところが、これが理解できない初心者(いや、経験1年以上なので、初心者とはいえないかもしれません)がいるのです。彼らの主張によると、「#ifndef FOO_Hのようにしているので(インクルードガードがあるので)、foo.hの内容が複数回有効になることはない」とのことです。

いろいろ話をしてみると、翻訳単位の概念がまったく理解できていないことが分かります。そうなってしまったのも無理もありません。ほぼ、Visual Studioのような統合開発環境しか使った経験がなく、あらかじめ用意された(あるいはツールが生成した)サンプルプロジェクトにすでに存在しているソースファイルを編集することばかりやってきたからです。

前述したように、彼らは根本的に理解する機会をほとんど与えられず、とりあえず動かすという目先の結果だけを追いかけるような教育しか受けていない場合がほとんどです。確かに、まったくの素人に対しては、とりあえずプログラミングの楽しさを味わわせるという意味で、そうした指導も悪くはないでしょう。しかし、その方針を1年も続けてしまうと、やはりいろいろな弊害が出てきます。

ただ、これは"ゆとり教育"の影響なのかどうかわかりませんが、面倒なこと、退屈なこと、難しいことはすぐに放棄してしまう者も少なくありません。というより、そのほうが多数派です。翻訳単位の概念の説明は、画面に絵を出すことに比べれば退屈なことは間違いありません。だからといって、そうしたことを放棄してしまうと、結局はプログラミングの面白さを味わうことそのものを放棄することになってしまいます。

この記事のトラックバックURL:

http://www.kijineko.co.jp/trackback/805
このエントリーを含むはてなブックマーク