K.Maebashi's BBS

ご自由に書き込んでください。雑談も可。
テスト書き込みの類はテスト用掲示板にどうぞ

[日付順表示] [日付順インデックス] [スレッド順インデックス]

新規投稿 | 開設者ホームページへ戻る | ヘルプ

[82] GLOBAL
投稿者:774RR
2007/02/20 02:13:25

発言数が少ないようなのでネタ振りなど。 http://kmaebashi.com/programmer/pointer.html では GLOBAL int global_variable; を推奨されているようですが、私は反対です。 hoge.h の中では必ず extern int global_variable; と書くべきだと考えます。 hoge.c の中で #include "hoge.h" int global_variable; と書いても ISO 文法上何の問題も無いので。 もし仮に hoge.c の中で #define GLOBAL_VARIABLE_DEFINE #include "hoge.h" #include "piyo.h" とかやっちゃうと hoge piyo 両方の大域変数が定義されてしまいます。 #undef GLOBAL_VARIABLE_DEFINE しますか?めんどくさいです。 ヘッダ中から別ヘッダを #include しているとそもそも分離不可能だし。 globals.c とか作るのは個人的には嫌っています。 >わざわざ同一の記述を複数の個所で行なうのは間違いのもとである こと自体は御意なのです。でも、 関数(原型)宣言と関数定義を両方書く必要があるなら、 大域変数の宣言と定義を両方書いても大差ないぢゃん、とか思う今日この頃。 皆様はどうお考えですか?
[この投稿を含むスレッドを表示] [この投稿を削除]
[83] Re:GLOBAL
投稿者:トル
2007/02/20 02:13:25

 はじめまして、トルと申します。  追加・削除する時は、分けると2箇所を修正する必要がありますから、分けない方が一箇所で済み、何かと楽ではないですか? >globals.c とか作るのは個人的には嫌っています。  私は嫌いではありませんよ。
[この投稿を含むスレッドを表示] [この投稿を削除]
[84] Re:GLOBAL
投稿者:kit
2007/02/20 02:13:25

> hoge.h の中では必ず > extern int global_variable; > と書くべきだと考えます。 僕も自分で一から書くソフトウェアでは、 GLOBAL のようなマクロは使わず、extern 宣言と、変数の 実体の定義と 2回書いてます。 手間と言えば手間なんですが、グローバル変数にするような ものは、必ず初期化する趣味なので、GLOBAL みたいな簡単な マクロでは対処できなかったりします (たとえ 0 や NULL で 初期化する場合でも、明示的に初期化するスタイルを採って ます)。 また、そもそもグローバル変数なんてほとんど使わないので、 手間的にはたいしたことないです。昔風のプログラムなら グローバル変数にする場合も、たいていは accessor/mutator 関数でラップして見かけは関数にしてしまうことがほとんど です。プロファイルとって効率が問題になるようだったら、 あとで実装をマクロに直すだけですから、最初からグローバル 変数として見せる必要があるとは思えません。逆に、最初は 変数で済んでいたものが、後になって変更時に手続きをフック したくなることは結構あります。(単に最初の仕様検討がいい 加減なだけだって話もありますが… ^^;) > globals.c とか作るのは個人的には嫌っています。 同じく globals.c みたいなものは作りません。 こういうのって、モジュール分けの原則に反してますよね。
[この投稿を含むスレッドを表示] [この投稿を削除]
[85] Re:GLOBAL
投稿者:(ぱ)
2007/02/20 02:13:25

>http://kmaebashi.com/programmer/pointer.html >では GLOBAL int global_variable; を推奨されているようですが、私は反対です。 うーん。 GLOBALに反対する根拠として一番大きいのは、私としては 「Cの構文をねじ曲げるようなマクロはよろしくない」という原則に 反しているからじゃないかな、と思っています。 #define BEGIN { みたいなシンタックスのレベルで改変を入れるようなマクロは確かに いろんな意味でまずいでしょう。 >hoge.c の中で >#include "hoge.h" >int global_variable; >と書いても ISO 文法上何の問題も無いので。 これはそうですね。 >もし仮に hoge.c の中で >#define GLOBAL_VARIABLE_DEFINE >#include "hoge.h" >#include "piyo.h" >とかやっちゃうと hoge piyo 両方の大域変数が定義されてしまいます。 私のヘッダファイルの切り分け方からすると、 http://kmaebashi.com/programmer/c_yota/module.html hoge.h, piyo.hが共にプライベートヘッダファイルならどこかでまとめて #define GLOBAL_VARIABLE_DEFINEして#includeしますし、 piyo.hが別モジュールのパブリックヘッダなら、グローバル変数は公開しないので この問題は起きないんですね。 >わざわざ同一の記述を複数の個所で行なうのは間違いのもとである このメリットは一応それなりの説得力はあるかと思っています。 が、私が実際これをどう使っているかというと、たとえばここで 公開しているソースでは、 http://kmaebashi.com/programmer/c_yota/calc_html/calc.html #ifdef GLOBAL_VARIABLE_DEFINE #define GLOBAL #else #define GLOBAL extern #endif GLOBAL CLC_Interpreter clc_current_interpreter; これ一個だけ… だったら必要ないじゃん、というのはもっともですね (^^;
[この投稿を含むスレッドを表示] [この投稿を削除]
[86] Re:GLOBAL
投稿者:(ぱ)
2007/02/20 02:13:25

>手間と言えば手間なんですが、グローバル変数にするような >ものは、必ず初期化する趣味なので、GLOBAL みたいな簡単な >マクロでは対処できなかったりします (たとえ 0 や NULL で >初期化する場合でも、明示的に初期化するスタイルを採って >ます)。 GLOBAL char *hoge[] #ifdef GLOBAL_VARIABLE_DEFINE = { "foo", "bar", } #endif /* GLOBAL_VARIABLE_DEFINE */ ; とか書いたこともありますけどね (^^; >また、そもそもグローバル変数なんてほとんど使わないので、 >手間的にはたいしたことないです。 別レスで書きましたけど、実は私もそうです。 別レスで挙げたCLC_Interpreterのように、構造体にまとめて malloc()で領域を確保することが多いです。 # わかりにくいですがCLC_Interpreterはポインタでして、 # こういうふうにポインタがポインタでないかのようにtypedefするのは # よろしくないなあ、と今は思っています。当時はXtとかのスタイルを見て # かっこいいと思ってしまったわけですが。 ## clc_current_interpreterのようなものを静的に持ってしまうと ## リエントラントでなくなります。当時はマルチスレッドなんて ## そうそう使わないよね、と思ってたわけですが… ## まあ、リエントラントにしたい場合も、外部のインタフェースにだけは影響を ## 与えないようにしてあるからまあ許容範囲かと。 >昔風のプログラムなら >グローバル変数にする場合も、たいていは accessor/mutator >関数でラップして見かけは関数にしてしまうことがほとんど >です。 たとえばclc_current_interpreterは関数でラップされていませんが、 CLCモジュールの外から見えることもありません。 これはモジュールの粒度をどのくらいにするかという問題だと思いますが、 「関連の強いソースの集合体としてのモジュール」内(せいぜい数千行レベル)で あれば、この程度のカプセル化の侵食は許容範囲じゃないかなあ、 と私は思っています。 もちろん最初からgetter/setterを書いたからといってさしたる手間でも ないですけれど。
[この投稿を含むスレッドを表示] [この投稿を削除]
[87] Re:GLOBAL
投稿者:774RR
2007/02/20 02:13:25

>hoge.h, piyo.hが共にプライベートヘッダファイルならどこかでまとめて >#define GLOBAL_VARIABLE_DEFINEして#includeしますし、 そのまとめて include っつーことは globals.c とか作るということですか? モジュール切り分け原則に反しているような気がしてなんとなくいやです。 >piyo.hが別モジュールのパブリックヘッダなら、グローバル変数は公開しないので >この問題は起きないんですね。 御意。ではあるのですが... 組み込み系では「状態保持」のための変数は、プログラムが生きている =電源が入っている限り、ずっと必要なので必然的に静的変数(大域変数)になっちゃいます。 んで getter/setter も最適化の都合でインライン関数化したかったりするんです。 っとなるとプライベートヘッダとパブリックヘッダの分離とか、 理想を追いかけていられない実装上の都合があったりするのです(泣)
[この投稿を含むスレッドを表示] [この投稿を削除]
[88] Re:GLOBAL
投稿者:(ぱ)
2007/02/20 02:13:25

>>hoge.h, piyo.hが共にプライベートヘッダファイルならどこかでまとめて >>#define GLOBAL_VARIABLE_DEFINEして#includeしますし、 >そのまとめて include っつーことは globals.c とか作るということですか? >モジュール切り分け原則に反しているような気がしてなんとなくいやです。 globals.cを作るか、ということですが、 そのglobals.cが、プログラム全域のグローバル変数の定義を行う、 ということなら、Noです。 あるモジュールについて、「そのモジュールの内部だけで使う、ソースを超えた スコープを持つ変数」の定義を行うglobal.cなら、作るかもしれません。 たとえば先のcalcの例だと、電卓モジュール「CLC」内にglobals.cを 置くかもしれません(モジュールごとにディレクトリが分けられていて、 ソースファイル名の重複が許されるとして)。 モジュールをまたがったglobals.cがあるなら「モジュール切り分け 原則に反している」と私も思いますが、モジュール内でしか見ない グローバル変数のためのglobals.cなら、問題ないと思います。 # ここでモジュールは「複数の.cの集合体」と定義しています。 ## Mayerさんの「オブジェクト指向入門」に「ヘッダファイルはモジュールを ## 破壊する」ってあったけど、使い方次第だと思うんだけどなあ。 ただ、実際には、ひとつのモジュールに、そんなにたくさんプライベート ヘッダファイルがあるわけはないので、どこかのソースで代表させて終わりです。 CLCの場合はinterface.cですね。 # どこのソースで代表させるかが不明確なので(たとえ3行しかなくても)globals.c # を書くべきだ、という主張には正当性があると思います。 >組み込み系では「状態保持」のための変数は、プログラムが生きている >=電源が入っている限り、ずっと必要なので必然的に静的変数(大域変数)になっちゃいます。 >んで getter/setter も最適化の都合でインライン関数化したかったりするんです。 なるほど。アクセサを書くことまではできても、ヘッダファイルを切り分けると、 コンパイル単位が分かれてしまうからインライン展開が効かず効率が悪くなる わけですね。 Javaなんかだと、javacによるコンパイルはソース単位ですが、 JITコンパイラが実行時にソースを超えたインライン展開までやってくれたり するようです。でも組み込みじゃ難しいですよね。
[この投稿を含むスレッドを表示] [この投稿を削除]