最後まで生き残る変数
グローバル変数の寿命
前節では、関数内で宣言した変数は関数内で寿命が尽きることを説明しました。
それならば、
関数外ではどうなのか、と考えるのが自然の成り行きです。
今まではすべての変数を関数内で宣言してきたのですが、実は関数外でも宣言できます。
関数外で宣言された変数のことを、
グローバル変数と呼ぶことがあります。
【グローバル変数】
関数外で宣言された変数。
プログラム全体が終了するまで生き残り続け、
宣言されたソースファイル内のすべての関数から使用できる。
次のプログラムは、グローバル変数を使った例です。
#include <stdio.h>
int count; /* グローバル変数 */
int countfunc(void);
int main(void)
{
countfunc();
countfunc();
countfunc();
return 0;
}
int countfunc(void)
{
count++;
printf("%d\n", count);
return count;
}
このプログラムの実行結果は、次の通りになります。
前章の時とは異なり、今回は見事に関数を呼び出した回数が数えられています。
これには、グローバル変数の寿命が深く関係しています。
グローバル変数の場合、プログラムの最後まで生き残ります。
したがって、変数が何度も呼ばれた場合でも、以前の数値を記憶しているのです。
ところで、上記のプログラムで変数countは初期化していないにもかかわらず、
きれいに 1、2、3 と出力されましたが、これは偶然ではありません。
グローバル変数は、プログラムの開始時に
自動的に0に初期化されるのです。
ローカル変数は関数の呼び出しのたびに作られるので、
そのたびに初期化しているとムダになるので自動的には初期化しないのですが、
グローバル変数は最初に1回だけ初期化すれば良いためです。
すべての関数で共有される
グローバル変数は、関数外で宣言された変数です。
関数内のローカル変数と違い、どの関数からでも自由に使えます。
次のプログラムは、main関数から変数countを変更する例です。
#include <stdio.h>
int count; /* グローバル変数 */
int countfunc(void);
int main(void)
{
countfunc();
count = 10; /* ここで変更 */
countfunc();
countfunc();
return 0;
}
int countfunc(void)
{
count++;
printf("%d\n", count);
return count;
}
このプログラムの実行結果は、次の通りになります。
この結果を見ると、2回目の表示では突然値が11になってしまっていますが、
これは、main関数内で、変数countを変更しているためです。
この様に、グローバル変数は、すべての関数で共有されます。
これは、どの関数からでも、代入や値の取得ができるということなので、便利なのですが、
他の関数でどのような使い方をしているか、十分に気を付けて使用しなくてはなりません。
グローバル変数を多用すると、変数名がたくさん必要になってしまい、とても面倒なことになります。
したがって、グローバル変数は、プログラム全体で共有する特別なデータだけに使い、
基本的にはローカル変数を使用することで、プログラムをわかりやすくできます。
ローカル変数は独立する
前項では、グローバル変数はすべての関数で共有されると説明しました。
もしも、関数内にグローバル変数と同じ名前のローカル変数がある場合、
どちらが優先されるのか、実験してみたいと思います。
次のプログラムは、main関数内で変数countを宣言してみた例です。
#include <stdio.h>
int count; /* グローバル変数 */
int countfunc(void);
int main(void)
{
int count; /* 同名で宣言 */
countfunc();
count = 10;
countfunc();
countfunc();
printf("main : count = %d\n", count);
return 0;
}
int countfunc(void)
{
count++;
printf("%d\n", count);
return count;
}
このプログラムの実行結果は、次の通りになります。
まず、このプログラムが実行できることから、
グローバル変数と同名のローカル変数を宣言できることがわかります。
どちらが優先されるのかを知るために結果を見てみると、
main関数内で変数countの値を変更しているにもかかわらず、
countfunc関数内の数値はまったく変更されていませんし、
main関数の最あとでは、しっかり関数内で代入した値が表示されています。
つまり、
グローバル変数と同名のローカル変数ではローカル変数が優先されるのです。
これも、前節で説明した、関数の独立性を維持するための仕組みです。
もし、グローバル変数が優先されるなら、関数をコピーして使う場合には、
その関数内の変数がグローバル変数と同じ名前か調べなくてはならず、面倒です。
ここではグローバル変数はすべての関数で共有されると説明しましたが、
正確には、1つのソースファイル内で共有されています。
たとえば、main.c ファイルの先頭で宣言されたグローバル変数は、
main.c ファイル内のすべての関数から代入や値の参照が可能ですが、
別のファイル、たとえば data.c ファイルの関数からは参照できません。
しかし、別のファイルに変数の名前と型を教えてやれば、
グローバル変数はすべてのファイルから使用できるようになります。
複数のソースファイルを使う方法はまだ説明していないので、
現段階では、すべての関数で共有されると考えても違和感ありません。