ページ 11

externで他のファイルから見えるようにする方法

Posted: 2011年11月10日(木) 17:36
by shiro4ao
現在3つのファイルにわけて1つのプログラムを書いています。
3ファイルで1つの変数Counterを共有したいのです(どのファイルからもアクセスできる)が方法がわかりません
以下の状態でコンパイルすると
Error: 外部シンボル '_Counter' が未解決
とでてきます。
なにか解決方法はありますでしょうか?それとも根本からおかしいのでしょうか?

===========main.c=============
#include "sub.h"
int Counter;
=============================

============sub.h============
#include "subsub.h"
extern int Counter;
=============================

============subsub.h=========
extern int Counter;
=============================

Re: externで他のファイルから見えるようにする方法

Posted: 2011年11月10日(木) 19:46
by 初級者
3つのファイルと書かれていたので、てっきり3つの.cファイルかと思いました。
今のコードは、main.cで
extern int Counter;
extern int Counter;
int Counter;
と書いたのと実質的に同じです。
本当にそういうことがしたいのでしょうか。

Re: externで他のファイルから見えるようにする方法

Posted: 2011年11月10日(木) 19:50
by beatle
3つのファイルというのは、main.c, sub.h, subsub.hの3つのことですか?

アプリをビルドする過程は大体次のようになっています。
この3段階をまとめて「コンパイル」と言う場合もあります。
  1. プリプロセス
  2. (狭義の)コンパイル
  3. リンク
あなたの提示した3つのファイルのうち、(狭義の)コンパイルをするファイルは
main.cのみですね。sub.hとsubsub.hはプリプロセスの段階でmain.cに展開されますからね。

そして、main.cの(狭義の)コンパイルは可能です。
一般に、(狭義の)コンパイル時には、「シンボル未解決」のエラーは出ません。

シンボル未解決のエラーが出るのはリンクのときです。リンクするときにはじめて
外部シンボルの解決が行われます。
(printf関数を使ったプログラムの場合、printf関数もこのときにリンクされます。)

したがって、「Error: 外部シンボル '_Counter' が未解決」のエラーが発生するとするなら
リンク時なのですが、残念ながらあなたの示したファイル群ではこのエラーは出ないのです。
main.cにint Counter;がありますからね。
(しかし、main関数が未解決なのでリンク自体は失敗します。)

想像なのですが、sub.hとかsubsub.hを(狭義の)コンパイルしようとしているのではないですか?
それならば、extern int Counter;しかしていないので、(狭義の)コンパイルはできません。

Re: externで他のファイルから見えるようにする方法

Posted: 2011年11月10日(木) 23:30
by shiro4ao
ご回答ありがとうございます。
生半可な知識でexternを誤解してしまっていました。

ヘッダファイルに実装する場合とソースファイルに実装する場合の違いを
理解せず書いていました。
ヘッダファイルはコピーと同じ事なので、わざわざexternしなくてよいのですね。

誤解がとけたのでこれにて解決とさせて頂きます。
細かいミスですみません。
ありがとうございました。

Re: externで他のファイルから見えるようにする方法

Posted: 2011年11月10日(木) 23:35
by beatle
本当に解決ですか?
くれぐれもヘッダファイルに

コード:

int Counter;
とか書かないでくださいね。

Re: externで他のファイルから見えるようにする方法

Posted: 2011年11月11日(金) 15:28
by shiro4ao
コンパイルに通るのでsubsub.hに
int Counter
と書いてしまいました・・・
危険なのでしょうか?

Re: externで他のファイルから見えるようにする方法

Posted: 2011年11月11日(金) 15:38
by beatle
shiro4ao さんが書きました:コンパイルに通るのでsubsub.hに
int Counter
と書いてしまいました・・・
危険なのでしょうか?
危険と言うか、リンク時に問題が発生します。
以下、具体例で説明します。

ヘッダファイルhoge.hに

コード:

int Counter;
と書いて、そのヘッダファイルをfoo.c, bar.cでincludeしたとしましょう。

foo.c

コード:

#include "hoge.h"
bar.c

コード:

#include "hoge.h"
すると、プリプロセスが終了した段階で次のようになりますね。

foo.c

コード:

int Counter;
bar.c

コード:

int Counter;
次にfoo.cとbar.cを(狭義の)コンパイルします。
(狭義の)コンパイルは、.cファイル1つずつに対して行われることに注目してください。
すると、オブジェクトファイルfoo.oとbar.oにそれぞれ、_Counterというシンボルが生成されます。

この状態でfoo.oとbar.oをリンクしようとすると、どちらの_Counterを使っていいのか
分からないというわけです。


だから普通はこうします。
hoge.h

コード:

extern int Counter;
foo.c

コード:

#include "hoge.h"
int Counter;
bar.c

コード:

#include "hoge.h"
// ここでは int Counter; を書かない
要するに、ヘッダではexternで「宣言」し、どれか一つのcファイルで「定義」するようにします。

Re: externで他のファイルから見えるようにする方法

Posted: 2011年11月11日(金) 20:32
by shiro4ao
具体的な説明ありがとうございます。

人間がファイル1つ1つをちゃんと把握しておかないといけないのですね。
ファイルに分けたら便利かと思いましたが、
1人で作るぶんには無意味に分割しないほうがよさそうですね。

Re: externで他のファイルから見えるようにする方法

Posted: 2011年11月11日(金) 21:43
by beatle
ファイル分割は無意味ではないですよ。
ガシガシ分割して、コンパイルの仕組みを学習しましょう!

Re: externで他のファイルから見えるようにする方法

Posted: 2011年11月11日(金) 21:57
by shiro4ao
将来、ファイル分割する可能性もあるので
すこしづつでも勉強していきたいと思います。