--年--月--日 --:--

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

C言語(C++)のincludeとexternと時々ファイル分割についての注意

2009年02月02日 14:14

※この記事は私の良心と「なんとなく」によって構成されています。間違ってたら優しくコメント欄に書き込んでください><

さて、昨日私が3時間悩んだこと…それはファイル分割!!! おかげで寝るの朝6時でした…
それはさておき、初めての人には、ソースファイルの分割というのはエグい話(C#では簡単だけど)。
では、コンパイルするとき、どういう所作をするのかを適当に書きます。
main.cppとsub.cppというソースがあるとします。

まず、コンパイラはmain.cppをコンパイルしようとします(どのファイルをコンパイルするのかについては、VisualStudioなら自動で判断。たぶん「ソースファイル」のフォルダ)
このとき、includeがあれば、コンパイル前にソースに丸々コピーします。ですから、ヘッダーに変数や関数が宣言されていれば、main.cppの先頭で関数のプロトタイプ宣言などがなされたことになります。
main.cppのコンパイルが終わると、sub.cppをコンパイルします。同様に、includeが有れば、内容をコピーします。

こんな感じです。


ここで、includeに関わる問題が2つあります。「2度インクルードしちゃうの><」という問題と「グローバル変数を2度宣言しちゃうの><」という問題です。
この2つは似ているように見えて、全く別物です。


まず、前者の2度インクルード問題。
これは、1つのソースファイルと2つのヘッダーファイルで発生します(もしくはそれ以上)。
次の状況を想定してください。
main.cpp:main.hをインクルード。sub.hをインクルード。
main.h:sub.hをインクルード
sub.h:特にインクルードはしない。
こいつをコンパイルすると、sub.hの内容がダブります
main.hには、sub.hの内容が丸々コピーされてますから、main.cppでincludeすると、「sub.hの内容がコピーされたmain.hの内容」がコピーされます。一方で、個別にsub.hの内容がコピーされるので、結局2度コピーされてます。

これの対処法は「インクルードガード」と呼ばれるモノです。特に難しくはないので、ググってください。
とはいえ、2度インクルードしようとするアホがいけないんです。main.cppでわざわざsub.hを読む必要は無いです。
ちなみに、「2度も定義すんなヴォケ!!」って類のことが言われます。


さて、今度はもう一つ「2度グローバル変数」問題です。
これは、2つのソースファイルと1つのヘッダーファイルで起こります(もしくはそれ以上)。
次の状況を想定してください。
main.h:グローバル変数を定義(クラスだと宣言でもダメかも)
main.cpp:main.hをinclude
sub.cpp:main.hをinclude
こいつをコンパイルすると、ソースファイルごとでは問題はありませんが、exe全体で問題が発生します
これはコンパイラの作動に注目してください。
コンパイラは、main.cppをコンパイルするとき、main.hの内容をコピーします。また、sub.cppをコンパイルするとき、main.hの内容をコピーします。そしてそれらをくっつけます。結果的に、main.hのグローバル変数は2度定義されます。
定義を2度するとまずいらしいです。

では、main.hの定義を外せば良いのかと思われますが、「じゃぁどこで定義するんだよ!!」って話になります。main.cppで定義をすると、sub.cppでは定義がなされなくなってしまいますし、両方で定義したら元の黙阿弥。
ということで「extern」というのを使います。
これは、変数を宣言するときにつけてあげて、「このプロジェクトのどこかで定義しておきますぜ」ってことらしいです。
つまり、main.hでexternつけて宣言(というのは値を代入しない)、main.cppで定義まで行えば、sub.cppのコンパイル時、externをつけられたグローバル変数を発見して定義されている場所を探そうと(この場合main.cpp)します。
で、うまく行くっぽい。
ちなみに、これもまた「2度定義すんなヴォケ」って類です。


さて、「インクルードガード」と「extern」について説明しました。
これらは、似通ってる部分が多すぎますが、大きく異なります。
大事なのは「1つのソースファイルと2つのヘッダーファイル」「2つのソースファイルと1つのヘッダーファイル」という部分ですから、対処法を誤てば、結果はあやまったものになります。

以上!!
スポンサーサイト


コメント

    コメントの投稿

    (コメント編集・削除に必要)
    (管理者にだけ表示を許可する)

    トラックバック

    この記事のトラックバックURL
    http://suiseidreaming.blog45.fc2.com/tb.php/198-fe37a389
    この記事へのトラックバック


    最近の記事


    上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。