苦しんで覚えるC言語

最後まで生き残る変数


第1項:グローバル変数の寿命

前節では、関数内で宣言した変数は関数内で寿命が尽きることを説明しました。
それならば、関数外ではどうなのか、と考えるのが自然の成り行きです。

今までは全ての変数を関数内で宣言してきたのですが、実は関数外でも宣言出来ます。
関数外で宣言された変数のことを、グローバル変数と呼ぶことがあります。
グローバル変数
関数外で宣言された変数。
プログラム全体が終了するまで生き残り続け、
宣言されたソースファイル内の全ての関数から使用出来る。
次のプログラムは、グローバル変数を使った例です。

#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;
}
このプログラムの実行結果は、次の通りになります。

1
2
3
前章の時とは異なり、今回は見事に関数を呼び出した回数が数えられています。
これには、グローバル変数の寿命が深く関係しています。
グローバル変数の場合、プログラムの最後まで生き残ります。
従って、変数が何度も呼ばれた場合でも、以前の数値を記憶しているのです。

ところで、上記のプログラムで変数countは初期化していないにもかかわらず、
きれいに 1、2、3 と出力されましたが、これは偶然ではありません。
グローバル変数は、プログラムの開始時に自動的に0に初期化されるのです。

ローカル変数は関数の呼び出しのたびに作られるので、
そのたびに初期化していると無駄になるので自動的には初期化しないのですが、
グローバル変数は最初に1回だけ初期化すれば良いためです。

目次に戻る

第2項:全ての関数で共有される

グローバル変数は、関数外で宣言された変数です。
関数内のローカル変数と違い、どの関数からでも自由に使えます。
次のプログラムは、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;
}
このプログラムの実行結果は、次の通りになります。

1
11
12
この結果を見ると、2回目の表示では突然値が11になってしまっていますが、
これは、main関数内で、変数countを変更しているためです。
この様に、グローバル変数は、全ての関数で共有されます。

これは、どの関数からでも、代入や値の取得が出来るということなので、
便利である反面、どこで値が変更されるかわからないという怖さもあります。
従って、グローバル変数は、プログラム全体で共有する特別なデータだけに使います。

目次に戻る

第3項:ローカル変数は独立する

前項では、グローバル変数は全ての関数で共有されると説明しました。
もしも、関数内にグローバル変数と同じ名前のローカル変数がある場合、
どちらが優先されるのか、実験してみたいと思います。
次のプログラムは、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;
}
このプログラムの実行結果は、次の通りになります。

1
2
3
main : count = 10
まず、このプログラムが実行出来ることから、
グローバル変数と同名のローカル変数を宣言出来ることがわかります。

どちらが優先されるのかを知るために結果を見てみると、
main関数内で変数countの値を変更しているにもかかわらず、
countfunc関数内の数値は全く変更されていませんし、
main関数の最後では、しっかり関数内で代入した値が表示されています。
つまり、グローバル変数と同名のローカル変数ではローカル変数が優先されるのです。

これも、前節で説明した、関数の独立性を維持するための仕組みです。
もし、グローバル変数が優先されるなら、関数をコピーして使う場合には、
その関数内の変数がグローバル変数と同じ名前か調べなくてはならず、面倒です。

ここではグローバル変数は全ての関数で共有されると説明しましたが、
正確には、1つのソースファイル内で共有されています。

例えば、main.cpp ファイルの先頭で宣言されたグローバル変数は、
main.cpp ファイル内の全ての関数から代入や値の参照が可能ですが、
別のファイル、例えば data.cpp ファイルの関数からは参照出来ません。

しかし、別のファイルに変数の名前と型を教えてやれば、
グローバル変数は全てのファイルから使用できるようになります。

複数のソースファイルを使う方法はまだ説明していないので、
現段階では、全ての関数で共有されると考えても違和感ありません。

目次に戻る