<ローカル変数とグローバル変数>

 

 関数の中で宣言した変数は、その関数内でしか参照できません。そのような変数をローカル変数と呼びます。

 

typedef struct data_record {

          char filename[32];

          long length;

          double *buf;

} myDATA;

 

int main(void) {

          myDATA *data[2], *result; /* myDATA型構造体のオブジェクトをmain()のローカル変数として宣言 */

          ...

}

 

 このように宣言したdataやresultは、mainの中では参照できますが、mainから呼び出した関数からは直接みることはできません。同様に、main以外の関数内で宣言された変数は、mainからはみることができません。関数間で値のやり取りをするには関数の引数や返却値として受け渡しをするしかないわけです。

 

 それに対し、main関数の外で宣言した変数は、グローバル変数と呼ばれ、すべての関数の中から直接アクセスすることが可能です。

 

typedef struct data_record {

          char filename[32];

          long length;

          double *buf;

} myDATA;

         

myDATA *data[2], *result;           /* myDATA型構造体のオブジェクトをグローバル変数として宣言 */

 

int main(void) {

          ...

}

 

 このようにしておけば、mainから関数を呼び出す時に、dataやresultを引数として渡さなくても、関数側で直接その値を参照したり、代入したりすることができます。

 

 実際には、今回の課題に関しては、データ用の配列はグローバル変数としたほうがプログラムとしてはすっきりするかも知れません。この課題に限らず、グローバル変数を使えば引数や返却値の扱いに頭を悩ませることもなくなり、プログラミングも楽になると思われがちです。

 

 しかし、特にたくさんの関数を含む大きなプログラムの場合は、グローバル変数に頼ると弊害が生じます。

 

int n;                       /* グローバル変数nを宣言 */

int main(void) {

          int i;

          n = 10;                                /* グローバル変数nに10を代入 */

          for (i = 0; i < n; i++) {           /* 10回ループを回すつもり */

                    ...

                    some_function();           /* 関数some_functionを呼び出し */

                    ...

          }

}

void some_function(void) {

          ...

          n += 1;            /* 関数some_functionの中からnの値をインクリメント */

          ...

}

 

 上の例では、nはグローバル変数で、mainからもsome_functionからもアクセス可能です。mainではn=10回ループを回しているつもりなのに、関数some_function内でnの値が変わってしまっているので…目も当てられない結果になります。

 

 もちろんこれは極端な例で、単純なプログラムではこのようなミスはまず起きませんが、大規模なプログラムになると、いつどこで(どの関数で)グローバル変数の値が書き換えられるかを把握しておくことは、非常に困難になります。

 

 つまり、グローバル変数に頼りすぎると、「機能単位の独立したモジュール化」という関数本来の目的が失われることになるわけです。従って、基本的には「できる限りローカル変数を用いて、関数とは引数と返却値でやり取りする」という習慣をつけた方がよいでしょう。

 

 

戻る