MMGamesロゴ  MMGames
Twitterシェアボタン  Facebookシェアボタン   
しんで覚えるC言語
しんで覚えるC言語

最後まで生き残る変数

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

今まではすべての変数を関数内で宣言してきたのですが、実は関数外でも宣言できます。
関数外で宣言された変数のことを、グローバル変数と呼ぶことがあります。

キーワード
【グローバル変数】

関数外で宣言された変数。
プログラム全体が終了するまで生き残り続け、
宣言されたソースファイル内のすべての関数から使用できる。


次のプログラムは、グローバル変数を使った例です。

ソースコード
#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回だけ初期化すれば良いためです。
すべての関数で共有される
グローバル変数は、関数外で宣言された変数です。
関数内のローカル変数と違い、どの関数からでも自由に使えます。
次のプログラムは、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を変更しているためです。
この様に、グローバル変数は、すべての関数で共有されます。

これは、どの関数からでも、代入や値の取得ができるということなので、便利なのですが、
他の関数でどのような使い方をしているか、十分に気を付けて使用しなくてはなりません。
グローバル変数を多用すると、変数名がたくさん必要になってしまい、とても面倒なことになります。

したがって、グローバル変数は、プログラム全体で共有する特別なデータだけに使い、
基本的にはローカル変数を使用することで、プログラムをわかりやすくできます。
ローカル変数は独立する
前項では、グローバル変数はすべての関数で共有されると説明しました。
もしも、関数内にグローバル変数と同じ名前のローカル変数がある場合、
どちらが優先されるのか、実験してみたいと思います。
次のプログラムは、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.c ファイルの先頭で宣言されたグローバル変数は、
main.c ファイル内のすべての関数から代入や値の参照が可能ですが、
別のファイル、たとえば data.c ファイルの関数からは参照できません。

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

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



本サイトについて

苦しんで覚えるC言語(苦C)は
C言語入門サイトの決定版です。
C言語の基本機能を体系立てて解説しており、
市販書籍と同等以上の完成度です。

第0部:プログラム概要編
  1. プログラムとは何か?
2章:プログラムの書き方
  1. 書き方のルール
  2. 書き方の慣習
  3. 練習問題2
3章:画面への表示
  1. 文字列の表示
  2. 改行文字
  3. 練習問題3
6章:キーボードからの入力
  1. 入力用の関数
  2. 入力の恐怖
  3. 練習問題6
9章:回数が決まっている繰り返し
  1. 繰り返しを行う文
  2. ループ動作の仕組み
  3. 練習問題9
10章:回数がわからない繰り返し
  1. 回数不明ループ
  2. 入力チェック
  3. 練習問題10
13章:複数の変数を一括して扱う
  1. 複数の変数をまとめて扱う
  2. 配列の使い方
  3. 練習問題13
20章:複数のソースファイル
  1. 最小限の分割
  2. 分割の定石
  3. 練習問題20

コメント
COMMENT

💬 コメント投稿欄を開く