グローバル変数の性質とその危険性 | 技術者が教える初心者さんのためのC言語

技術者が教える初心者さんのためのC言語

〜最小限の知識でプログラム〜

いつも感謝しています。Nです。


前回の記事「
変数の有効範囲1(ローカル変数)」で

ローカル変数の有効範囲についてお話ししました。


おさらいをすると、

1: 変数には有効範囲がある

2: 変数の宣言される場所によって有効範囲は変わる

3: 有効範囲から分類すると、変数はローカル変数とグローバル変数に分類できる

4: 関数の括弧{ }の中で宣言された変数はローカル変数という

5: ローカル変数の使用出来る範囲は、それが宣言されている関数の括弧{ }の中でした。


今回はグローバル変数についてお話しをしますね。


グローバル変数は、一見非常に便利に思えるのですが、思わぬバグを引き起こす原因になりやすいです。

なので、あまり私はグローバル変数の多用は推奨しません。


しかし、グローバル変数がどういうものかを知っておくことは必要だと思います。


なぜなら

1: 他人の書いたプログラムにグローバル変数があった場合、知識として必要

2: グローバル変数の性質を知っておくことで、バグが生じたときに「もしかして?」という考えをもてる

からです。


では、具体的にお話ししますね。


グローバル変数で押さえておくことしては、

1: 宣言される場所が、関数の外側

2: グローバル変数の使える範囲は、プログラム全体

です。


サンプルプログラムで説明しますね。


#include <stdio.h>


void myFunc( void );


int  a;


int main( void )

{

   a = 0;

   printf(“a[main]=%d¥n”,a);

   myFunc();


   return( 0 );

}


void myFunc( void )

{

   a++;

   printf(“a[myFunc]=%d¥n”,a);

}


実行結果:

a[main]=0

a[myFunc]=1


まず、

int a; の場所に注目してください。関数の外で変数宣言がされていますね。


このように、関数の外で宣言された変数をグローバル変数といいます。


次に、この変数aが使われている場所に注目してくだい。main関数、自作関数myFuncの中でも使えていますね。


つまり、グローバル変数はどこでも使えるという性質をもっています。


もしかすると、ローカル変数よりもグローバル変数の方が便利だなぁと思われた方がいるかもしれません。

確かに、グローバル変数はどこでも使えるので便利だと思います。


しかし、この「どこでも使える」というのがクセ者です。


今回のサンプルプログラムのように、非常に短いプログラムであれば


どこで、どのグローバル変数を使ったか

どのようなタイミングでどのグローバル変数が動作するか


を把握できるのですが、


これが、

1: 数万行のプログラム

2: 複数のソースファイルにまたがる

3: 他人と共同してプログラムをつくる

のようになってくると、


どこで、どのグローバル変数を使ったか

どのようなタイミングでどのグローバル変数が動作するか


を把握するのが、どこでも使えてしまうので、非常に難しくなってきます。


たとえば、ちょっと極端な例ですが、

A君とB君がプログラムを分担して作っていたとします。


A君は、グローバル変数が一つづつプラスされる関数を作っていたとします。


次に、

B君の関数が出来上がったので、それをA君が用いたとします。


しかし、B君のプログラムに、グローバル変数を2倍する仕組みが組み込まれてA君はそれを知らなかった場合、

これは、バグになります。


極端なサンプルプログラムですが、以下のような感覚です。


#include <stdio.h>


void A_func( void );

void B_func( void );


int a = 0;


int main( void )

{

   /* A君の自作関数 */

 A_func();

   /* B君の自作関数 */

   B_func();


   /* A君は驚くだろう。。。(バグにつながる) */

   printf(“a=%d¥n”,a);


   return( 0 );

}


void A_func( void )

{

   a++

}


void B_func( void )

{

   /* B君の自作関数処理色々 */

 ・・・・・・・・


 /* グローバル変数aを2倍する処理(A君知らない) */

 a = a * 2;


   /* B君の自作関数処理色々 */

 ・・・・・・・・

}



以上、今回はグローバル変数の性質とその危険性についてお話ししました。