第35回
変数の通用範囲~内部広域変数と外部広域変数

複数のソースから1つのプログラムを作る

先に『このソースの外(ほかのオブジェクトやライブラリ)に存在する』と書きました。『ソースの外』ということは、1つのプログラムが複数のソースファイルから構成されていることを意味しています。

役割別にソースを分ける

Cでは、1つの.cソースファイルをコンパイルすることで1つの.obj中間ファイルが生成されます。しかし、1つのプログラムが1つの中間ファイルだけで構成されている必要はありません。

すでに説明してきたように、リンクの段階ではプログラムの初期化を行うスタートアップルーチンや関数の含まれるライブラリと、コンパイルされた中間ファイルとが結合されます。つまり、複数の中間ファイルが結合されて、最終的に1つのプログラム──実行形式ファイルが生成されるわけです。

したがって、1つのプログラムを複数のソースファイルに分けて記述しても構いません。というより、大規模なプログラムでは
main関数を始めとする基幹的な処理
画面表示に関わる処理
データの入力と計算に関わる処理
ファイル入出力関係の処理
プリント関係の処理
        :
といったように、役割別にソースファイルを分けて記述するのが一般的です。すべての処理を1つのファイルにまとめてしまうと、改良など後々のメンテナンスで手間取ってしまうためです。

マルチモジュール開発

1つのソースファイルから生成される一定の処理の領域を「モジュール(module)」と呼びます。スタートアップルーチンやライブラリも、それぞれがモジュールです。つまり、プログラムは複数のモジュールが結合してできているということです。

モジュールの中で宣言された変数は、モジュール内のすべての関数から参照できる広域変数だと説明しました。広域変数には、これ以外にほかのモジュールからも参照できるものがあります。

前者(モジュール内でのみ参照できる広域変数)を内部変数、後者(ほかのモジュールからも参照できる広域変数)を外部変数と呼びます。

リスト2で取り上げたextern修飾子は、モジュールの外(ほかのモジュール内)で宣言されている識別子(変数、関数)を自身のモジュール内でも参照できるようにするための指示です。

複数のソースファイルから1つのプログラムを生成するマルチモジュール開発については、もう少し回を追ってから詳述します。ここでは、広域変数にはソース内で宣言された内部広域変数と、ソースの外で宣言されている(はずの)外部広域変数の2種類がある、ということを押さえておきましょう。

なお、内部広域変数と外部広域変数の違いは、自動変数と静的変数のような変数の種類の違いではなく、同じ1つの変数の見え方が『宣言した場所』によって異なる――という違いです。広域変数を実際に宣言したソース内では、それは内部広域変数となります。それ以外のソースでその変数を参照する場合には、同じ変数が外部広域変数となります。