• ベストアンサー

複数ファイルで使うグローバル変数の位置

メイン関数の処理で、関数A→関数B→関数Cという順序で関数が呼び出される場合(1関数1ファイルとします)、関数A,B,Cすべてで使用するグローバル変数の宣言を関数Bのファイルでおこなって、他のファイルではそれをexternするというのでも問題ないでしょうか?

質問者が選んだベストアンサー

  • ベストアンサー
  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.2

問題ありません。 が、しかし、そのような方法は、実務レベルの場合は、行いません。 以下のような方法をとります。 ファイル名:xxx_ext.c 変数のみを宣言したファイル。 ファイル名:xxx_ext.h 上記の変数のみを宣言したしものをexternで参照するファイル。 ファイル名:func_a.c 関数Aのファイル。 このファイルで、#include xxx_ext.h する ファイル名:func_b.c 関数Bのファイル。 このファイルで、#include xxx_ext.h する ファイル名:func_c.c 関数Cのファイル。 このファイルで、#include xxx_ext.h する 上記のようにすることで、externで参照する変数が1つのファイル内に閉じこめられるのでメンテナンス性がよくなります。たとえば、ある理由があって、変数Xの型をintからdoubleに変えることを想定してください。 xxx_ext.c とxxx_ext.hの2つのファイルのみが変更対象 となります。 上記のようにしない場合は、3つのファイル(あるいはそれ以上)を変えることになります。

BIGMON
質問者

お礼

詳しい説明ありがとうございます。今回の場合はxxx_ext.h はあるのですが、xxx_ext.cがなくて、どこにグローバル変数をおいたらいいか困っていたところです。xxx_ext.cを作ればいいのですが、融通がきかないものでして。。。

すると、全ての回答が全文表示されます。

その他の回答 (4)

  • ency
  • ベストアンサー率39% (93/238)
回答No.5

No3 ency です。 No4 rentahero さん: > #3のようにするなら、C++にしてクラスにした方がいいのでは。 確かにそうなんですけどね。 プロジェクトで使用する言語って、個人がどうとか言ってどうになるものでもないですし。。。 # ちなみに、私は組込み系やってます。 # アプリ系は C++ を使ったりしているようですが、下回りはまだまだ # C から離れられないですね。 # ドライバ屋さんなんかは、アセンブラ使ったりしているところも # ありますからね。 No4 rentahero さんの参考 URL の方法は、よく見かける方法ですね。 ただ、extern をはずすマクロをどこで define するかという話がありますし、これって結局「どこに定義するべきか?」というのと同じ話になりそうな気がします。 でも、ヘッダファイルとの不整合が発生しにくいという点では、良い方法ですね。 あと、No3 の例で、ヘッダファイルに extern が抜けてますね。。。 # 失礼しました。

BIGMON
質問者

お礼

皆様解答ありがとうございます。最初はグローバル変数は使わないでstatic宣言してget関数set関数をつくって対応するはずだったんですが、関数の数も変えてはいけないことになってしまったもので。。。大変参考になりました。

すると、全ての回答が全文表示されます。
  • rentahero
  • ベストアンサー率53% (182/342)
回答No.4

#3のようにするなら、C++にしてクラスにした方がいいのでは。 まあともかく。 私もグローバル変数を使いたくないのはやまやまなので、私ならそのグローバル変数を使う関数をひとつのファイルにまとめるようにしますね。それならファイルスコープ変数ですみますから。 グローバル変数を使うときのうまいやり方が Cプログラミング診断室(参考URL参照)に紹介されています。 あと別解として、グローバル変数の代わりに構造体をつくり、mainにてstaticで静的に確保し、各関数にポインタを渡してやればよいのでは?

参考URL:
http://www.pro.or.jp/~fuji/mybooks/cdiag/cdiag.5.4.html
すると、全ての回答が全文表示されます。
  • ency
  • ベストアンサー率39% (93/238)
回答No.3

ファイル分割する際には、機能ごとにファイルを分割すると思います。 で、いくら全体から参照される変数とはいえ、その変数はどこかの機能に属しているはずです。 通常は、その属しているファイルに定義すれば良いと思います。 それで、ファイルスコープの変数定義をしておいて、アクセス用の関数を用意します。 ------------------------------------------------ hoge.h ------------------------------------------------ int hoge_get_nantoka( void ); ------------------------------------------------ ------------------------------------------------ hoge.c ------------------------------------------------ #include "hoge.h" static int hoge_nantoka; static void hoge_hoge_kantoka( void ); int hoge_get_nantoka( void ) { return hoge_nantoka; } static void hoge_hoge_kantoka( void ) { hoge_nantoka = 100; } ------------------------------------------------ ------------------------------------------------ piyo.c ------------------------------------------------ #include "hoge.h" int piyo_print_nantoka( void ) { printf( "nantoka=%d\n", hoge_get_nantoka()); } ------------------------------------------------ 理由は、他のモジュールから無条件で書き換え可能な変数は作りたくないからです。 # というか、他の人に悪さされたくなかったら、このような設計に # なってしまうと思います。 複数ファイルから、書き換えが発生するグローバル変数は極力避けたほうが良いと思います。 # 現実的に無理な場合もあるでしょうけど、そのような場合には # ファイル分割の仕方を見直すべきだと思います。 いわゆる「カプセル化」ってやつですね。 オブジェクト指向でなくても、このようなことは複数人で運営しているプロジェクトなら、当たり前のようにやっていると思います。 # 知らない人に、知らないところで、実は変数書き換えられていました、 # なんてことを起こさないためにもね。 さて、そうはいってもモジュールが機能追加等でだんだん大きくなってきて、同じモジュールでもファイル分割をする必要が出てくることもあるでしょう。 その場合、ヘッダファイルもモジュール内部用のヘッダファイルと、モジュール外用のいわゆる公開ヘッダファイルに分割すると良いでしょう。 ------------------------------------------------ hoge.h ------------------------------------------------ /* 公開ヘッダファイル */ int hoge_get_nantoka( void ); ------------------------------------------------ ------------------------------------------------ hoge_prv.h ------------------------------------------------ /* hoge のプライベートヘッダファイル */ /* 公開ヘッダファイルはインクルードしておく*/ #include "hoge.h" int hoge_nantoka; void hoge_hoge_kantoka( void ); ------------------------------------------------ ------------------------------------------------ hoge_a.c ------------------------------------------------ /* プライベートヘッダファイルをインクルードする */ #include "hoge_prv.h" int hoge_get_nantoka( void ) { return hoge_nantoka; } ------------------------------------------------ ------------------------------------------------ hoge_b.c ------------------------------------------------ /* プライベートヘッダファイルをインクルードする */ #include "hoge_prv.h" void hoge_hoge_kantoka( void ) { hoge_nantoka = 100; } ------------------------------------------------ ------------------------------------------------ piyo.c ------------------------------------------------ /* hoge の公開ヘッダファイルをインクルードする */ #include "hoge.h" int piyo_print_nantoka( void ) { printf( "nantoka=%d\n", hoge_get_nantoka()); } ------------------------------------------------ このようにしておけば、万が一他のモジュールからのアクセスがあった場合、運がよければエラーをはいてくれますし、最悪でも警告は出してくれるはずです。 # ヘッダファイルの中でヘッダファイルをインクルードすることに対する # 賛否はあるようですけど、私はこうしています。 ま、話が本来の趣旨とは関係ない方向に行ってしまいましたが。。。 これがふつうだと思っていたんだけど、どうなんでしょうかねぇ。。。 # 誰に教わったとか言うんじゃないけど、実運用上こうしないと # 余計なバグの温床になりかねないと思いますし。

すると、全ての回答が全文表示されます。
  • -izayoi-
  • ベストアンサー率45% (48/105)
回答No.1

問題ないですよ。

BIGMON
質問者

お礼

解答ありがとうございます。安心しました。関数Aだけで異常終了してしまった場合関数Bは通らないのに大丈夫かなあ?という気がしてしまうものですから。。。

すると、全ての回答が全文表示されます。

関連するQ&A