大域変数は使わない

 なぜ,大域変数は使わない方が良いか, 次のようなプログラムを例にとって,解説しよう.

int data[N], a[N], b[N];         /* 大域変数 */
int total;                       /* 大域変数 */

...........................
...........................
この間に,他の大域変数や関数の宣言定義
...........................
...........................

void sum()
{
    int i;
    for (i = 0; i < N; i++) {
        total += data[i];
    }
}

...........................
...........................

void set()
{
    int i;
    for (i = 0; i < N; i++) {
        data[i] = a[i] + b[i];
    }
}

...........................
...........................
数百行のプログラムコード
...........................
...........................

main()
{
    ...........................
    ...........................
    ...........................
    set();
    ...........................
    ...........................
    ...........................
    sum()
    ...........................
    ...........................
    ...........................
}

 さて,ここでこの sum() が,はたして何をしているのか? といことを,この関数呼び出しの部分だけを見て,想像することができるであろうか.「何か総和を求めているらしいが,何の総和なのか,求めた結果がどこにあるのか,さっぱり分からない. sum の関数定義を探し出し,それを見ると,どうやら大域変数の配列 data の総和を求めて,それを同じく大域変数の total にしまい込んでいるらしい.でも, data の数値はどこで定義されているのか,分からない. プログラム全体を通して見て,やっと set という関数で定義されているらしい,ということが分かる.

 このようなプログラムの分かりにくさの原因は,関数が使用する変数が関数の引数に与えられることなく,関数が大域変数を直接使用している,ということである。 ところが,setsum に次のような引数があったらどうであろう.

main()
{
    int data[N], a[N], b[N];
    int total;
    ...........................
    ...........................
    ...........................
    set(data, a, b);
    ...........................
    ...........................
    ...........................
    sum(data, &total);
    ...........................
    ...........................
    ...........................
}

これならば,setsum が何をしているのかが,その関数呼び出しを見ただけで想像できるし,少なくとも,それらの関数が何を使っているのかは明瞭となる.

 ここまで読んで分かるかと思うが,大域変数を使うそのこと自体が悪いのではなくて,関数で使用するものを引数に与えない,ということが悪いのである。 つぎのことを良く憶えておこう

関数で使用するものは,すべて引数で与えるべきである。

 

Valid HTML 4.01!