いつも感謝しています。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君の自作関数処理色々 */
・・・・・・・・
}
以上、今回はグローバル変数の性質とその危険性についてお話ししました。