2013年2月2日土曜日

グローバル変数の危険性

プログラムで何でも便利だからといって何でもかんでもグローバル変数にするのはよくありません。



以下の3つのソースコードがあるとします。

func.h
#ifndef FUNC_H
#define FUNC_H

void func(void);

#endif

func.c
#include "func.h"

int a;

void func(void)
{
  a = 0;
}

main.c
#include<stdio.h>
#include "func.h"

extern int a;

int main()
{
  a = 2;
  printf("a = %d\n", a);
  func();
  printf("a = %d\n", a);

  return 0;
}

func.cの中でグローバル変数aを宣言しています。
func.cの作成者はまさかこれが外部からいじられないと思っているようですが、実はexternという修飾子を用いると、他のCファイル内で用いることができます。

これらのプログラムをコンパイルして実行すると結果は以下のようになります。
a = 2
a = 0
最初のaはmain関数内で代入された値の2を表示していますが、func()が呼び出された後はaの値も変わってしまってます。

このようにグローバル変数は時に予期しない挙動を示すことがあるので注意が必要です。

どうしても、グローバル変数を使う必要がある場合はstatic修飾子を付けるようにしましょう。
 この場合だと、func.cの3行目の宣言を次のようにします。
static int a;
こうすることでaのスコープがfunc.cの中だけに収まるのでmain.cから呼び出すことが不可能になり、コンパイルの時点でエラーを見つけてくれるようになります。

ほんとは関数のスコープに関して書きたかったんですがそれはまた次の機会に。


0 件のコメント :

コメントを投稿