■ほとんど同じ■それぞれ、「対」になるファイルの相違点は何でしょうか?一方にはexternがあり、他方にはな いだけでしょう。これならば、一方のファイルをコピーし、externの部分だけを書き換えれば、他 方のファイルができてしまうでしょう。きわめて機械的な単純な変更作業ではないですか。我々は、機械的な作業だけが何よりも得意なコンピュータのプログラムを組んでいるのですから、 このような作業は、当然コンピュータにやらせるべきです。では、どうすれば良いでしょうか。 まず考えられるのが、externのついているファイルから、externを取り除いてしまうツールを作 ることでしょうか。これでも、ちょっと問題になるのは、グローバル変数に初期値が代入されてい る個所があることです。この部分は、逆になるので、一方から他方を単純には作れません。 では、両方を含むファイルを作り、ツールで、内部で宣言するファイルと、extern宣言するファ イルを作るとよいですね。代入部分は、extern宣言する方のファイルに対しては削除します。これ で、めでたく解決ですかね。では、そのツールの仕様と作成は読者にまかせましょうか。 ■マクロで対処■さて、ツールはできましたか。でも、本当はツールなど作る必要もないのです。ほとんど似てい るものを作る時こそ、「マクロの出番」なのです。もしツールを作っていたら「バカ」です。externになったり、ブランクになったりするのは、グローバル変数を、そこで確保したいか、他 で確保(extern)させたいかなので、その判定をする基準となるものが必要になります。そのために、 ここでは、GLOBAL_VALUE_DEFINE というマクロ名をフラグとして使うことにしましょう。このマク ロ名が#defineで定義されているときは、ここで変数を宣言し、未定義のときはextern宣言します。 このためには、 #ifdef GLOBAL_VALUE_DEFINE #define GLOBAL #else #define GLOBAL extern #endifのように、#ifdefでGLOBALというマクロ名を空白かexternに置換します。これで、 GLOBAL short SV_HEAD;と書かれていた個所のGLOBALの部分は、希望通りに置換されます。GLOBAL_VALUE_DEFINE はどこか のファイルで定義してしまえば、これで終りです。今回の例では、table.c の先頭に入れておくの が適当なようです。つまり、mktable.c の先頭を、 #define GLOBAL_VALUE_DEFINE #include "defglobal.h" #include "dbstruct.h" #include "data.h"のように書くことで、全てのグローバル変数の実体をメモリ上に確保し、他のファイルからは全部 外部参照すると美しいですね。 ■初期値設定■グローバル変数にも、初期値設定が必要なことがあります。今回の例では、int chrx_d = 8; int chry_d = 16; int crtbias = 0;のような初期値があります。' = 8 ' の部分もGLOBAL_VALUE_DEFINEによって、無くしたり、その まま残したりしなければいけません。 これもマクロで対応できます。 #define GLOBAL_VAL(v) = (v)というマクロがあると、 GLOBAL int chrx_d GLOBAL_VAL(8); GLOBAL int chry_d GLOBAL_VAL(16); GLOBAL int crtbias GLOBAL_VAL(0);は、元のように展開されますね。代入部分を無くすには、 #define GLOBAL_VAL(v) /* */としておきます。/* */ の部分は、もちろん無くても構いません。「無くなるよ」ということを強 調しているだけです。したがって、前のと一緒にすると、 #ifdef GLOBAL_VALUE_DEFINE #define GLOBAL #define GLOBAL_VAL(v) = (v) #else #define GLOBAL extern #define GLOBAL_VAL(v) /* */ #endifと書けばいいですね。 Cプリプロセッサのマクロ展開(置換)は、単なる文字列の置き換えをしているだけですから、 このようなことが簡単にできます。
|
ナンプレ問題 |