|
分類:[C/C++]
Cの多重インクルードの防止に関して質問させてもらいたいのですが、 #include は指定ファイルをそこを展開するものだと認識しています。 その前提で、もし多重インクルード防止のため、
#ifndef _INC_HEADER_ #define _INC_HEADER_ <いろいろな定義> #endif
として、A.c と B.c でそのヘッダをインクルードしたとします。
[質問@] 各ソースがコンパイルされる際、 例えば A.c が先にコンパイルされるとして、 _INC_HEADER_ が #define されます。
その後、B.c は既に _INC_HEADER_ が #define されていることを知っているのでしょうか? それはどのようにして知るのでしょうか? もし、#define されていることを知らないのであれば、 ヘッダ内の定義が、両ソースにて展開されてしまうのではないか?と思います。
[質問A] また、#define されたことを知っているとしたならば、 B.c は #ifndef により、ヘッダ内の定義が無視されることになると思いますが、 B.c 内でヘッダに定義されている"何か"を使用しようとした場合、 認識できるのでしょうか? コンパイルエラーになりそうな気がしてしまうのですが・・・ (定義が見つからない)
[質問B] 上記の質問内容と交えて混乱してしまっているのですが、 コンパイルオプション(/P)にて、プリプロセッサの前処理済みファイル(.i)を出力するようにしました。 結果、A.c にも B.c にも #ifndef されているにもかかわらず、 ヘッダの定義内容が展開されていました。 定義が複数箇所に散らばっていることでコンパイルエラーにはならない? 定義の重複はリンク時に判定される?
[質問C] これらを検証するために、 最初に、ヘッダに構造体、extern無し変数、#defineマクロを 定義し、"多重インクルード防止無し"で、A.c と B.c からインクルードしてコンパイルしました。 (もちろん、#pragma once も無し) 質問Bで記した通り、A.i と B.i の両方、定義が展開されました。 少なくとも、構造体やマクロが多重定義されている旨のコンパイルエラーが出るかと思ったら、 出ませんでした。 とても不思議です・・・ どのような場合に定義の重複エラーと見なされるのでしょうか? そもそも、私の検証内容自体に問題があるために、 上記の疑問が出てきているだけなのでしょうか?
環境は、XP・VC2008 Express です。
よろしくお願いします。
|