グローバル変数

出典: フリー百科事典『ウィキペディア(Wikipedia)』
移動: 案内検索

グローバル変数大域変数: global variable)は、コンピュータプログラミングにおいて全てのスコープからアクセスできる変数のことである。対する語は、ローカル変数である。スコープも参照。

一般にグローバル変数は、その非局在的な性質ゆえに、好ましくない実践だと考えられている。すなわち、グローバル変数は潜在的にどこかで変更される可能性があり、またプログラムの一部はそれに依存してしまう恐れがあるからである。グローバル変数はそれゆえ相互依存を生み出す無限の可能性を持っており、相互依存が高まることは複雑性を増大することにつながる。遠隔作用 (Action at a distance) を参照。

しかしグローバル変数が適する状況もある。例えば、様々な関数を通して継続的によく使われる変数を引数として渡すことを避けるために使用できる。また、並列実行するスレッドシグナルハンドラのように、呼び出し側/被呼び出し側の関係を持たないコード同士でセクション間情報を受け渡すためにも広く使われる。

各々のファイルが暗黙の名前空間(無名名前空間)を定義するような言語では、グローバルな名前空間を持つ言語に見られる問題の多くが解消されているが、一部の問題は適切なカプセル化を行わなければ解決できない。(ミューテックスのような)適切なロック無しにグローバル変数を使用しているコードは、保護メモリ内の読み出し専用値以外はスレッドセーフではない。

C++におけるグローバル変数の例:

#include <iostream>
 
int global = 3 ; // これはグローバル変数。
 
void ChangeGlobal ()
  {
  global = 5 ; // 関数でグローバル変数を参照。
  }
 
int main (int argc, char *argv [])
  {
  std::cout << global << std::endl ; // もう一つの関数でグローバル変数を参照。
  ChangeGlobal () ;
  std::cout << global << std::endl ;
  return 0 ;
  }

この変数はグローバルなので、main以外の全ての関数にそれを引数として渡す必要がない。グローバル変数はプログラム内で、全ての関数に属する。

この出力結果は、以下のようになる:

3
5

グローバル変数を使用すると、ソフトウエアのソースコードを理解することが困難になる。グローバル変数の値はプログラムのどこからでも変更できるため、グローバル変数がどのように使用されているか理解するためには、プログラム全体を把握しなければならないからである。

以下にグローバル変数により難解になる例を示す:

int a, b, c ; // グローバル変数宣言
int main (int argc, char *argv [])
  {
  FunctionA () ; // グローバル変数cを書き換える
  FunctionB () ; // グローバル変数cを元にグローバル変数aを書き換える
  FunctionC () ; // グローバル変数a, cを元にグローバル変数bを書き換える
  return 0 ;
  }

上記をローカル変数を用いて書きなおした例:

int main (int argc, chra *arg [])
  {
  int c = FunctionA () ; // ローカル変数cを書き換える
  int a = FunctionB (c) ; // ローカル変数cを元にローカル変数aを書き換える
  int b = FunctionC (a, c) ; // ローカル変数a, cを元にローカル変数bを書き換える
  return 0 ;
  }

ローカル変数を用いた例ではどの変数が、どの関数呼び出しに作用し、どの関数呼び出しの結果を保持しているかは一目瞭然である。対して、グローバル変数を使用した例では、関数の呼び出し側だけを見てどの関数がどの変数に影響を与えるかを判断することはできない。また、ローカル変数を用いた例では関数の呼び出し順序を入れ替えることは引数と戻り値だけ意識すれば良く容易であるのに対して、グローバル変数を用いた例ではグローバル変数の作用を全て把握する必要があるため困難である。特にこの困難度合いは、グローバル変数の数とグローバル変数を操作する可能性のある関数の数に比例する。

DLLのような)多くのシステムは他のモジュールにあるグローバル変数の参照を直接サポートしないため、グローバル変数が多用されているコードを分割して再利用ライブラリにすることは非常に困難である。また、グローバル変数が他のローカルまたはオブジェクトスコープ変数として代用するには危険な名前を作るために起こる名前問題を導いてしまうことがある。グローバル変数と同じ名前のローカル変数は、一般にそのローカル変数のスコープにおいてグローバル変数を隠匿する。そのため、さらにコードの理解を困難にする。グローバル変数への値の書き込みは理解と予測を難しくする副作用を生み出す。グローバルなどの利用はユニットテストを目的とするコード分割をより難しくする。それゆえ、それらは直接にコードの質の低下を助長する。

関連項目[編集]