第34回
変数の通用範囲~自動変数と静的変数/局所変数と広域変数

変数の通用期間

変数はデータの『入れ物』であり、型によって保存するデータの性質とサイズ(メモリ上に占有するバイト数)とが規定される──ということはすでに説明しました。さらに変数には、それがメモリ上に存在している『期間』があります。

変数の寿命

変数は型と名前を明らかにすることで宣言され、それによってメモリ上に変数のための領域が確保されます。

メモリ上に確保された変数の領域には『通用期間』(または『適用期間』)があります。一般に、変数だけではなく関数も含めてプログラムで確保されたメモリ領域は、プログラムの開始時に確保されて終了時に解放 ※1 される──ということになります。

関数は基本的にこのルールに従い、プログラムの開始から終了までの間、メモリ上に存在し続けます。しかし変数の場合は、プログラムの開始から終了までの間よりも短い期間だけ存在するものがあります。

「解放」とは、その変数や関数のためにメモリを確保したプログラムの管理を離れ、他の目的や他のプログラムのために使用できる状態となることを指します

自動変数

以下のswap関数は、引数として受け取った2つのポインタの示す値を入れ替えます。
void swap(int *a, int *b)
{
  int buf; -------- 関数内でのみ存在する変数
  buf = *a;
  *a = *b;
  *b = buf;
}

ある処理の中から以下のようにしてswap関数を呼び出すと、引数のxとyの保持する値が入れ替わります。引数には&x、&yのように変数名の前にアドレス演算子&を付け、変数の値ではなくアドレスを渡すことに注意してください。
int x, y;
x = 10;
y = 100;
swap(&x, &y); -------- この時点でxが100、yが10になる

このswap関数の定義内(“ { ”と“ } ”の間)で宣言されているint型の変数bufは、関数内の処理が終了してプログラムの流れが呼び出し元に戻ったときには消滅しています。変数が消滅すると確保されていたメモリ領域が解放され、他の用途に使用できる状態になります。

このように、関数の中で宣言されて関数の終了とともに消滅する変数を『自動変数』と呼びます。自動変数は、正式にはautoという修飾子を付けて“auto int buf;”のように宣言するのですが、これは省略できます。つまり、関数内部で特に指示なく型と名前によって宣言された変数は、暗黙のうちに自動変数とみなされます。


関数の引数も自動変数

swap関数は、引数をポインタで渡すことの意味を説明する際に、例としてよく用いられます。

以下のように引数を直接の値で受け取ってしまうと、関数の中ではたしかに値が入れ替えられるのですが、それを呼び出した側では何の変化も起きません。
void swap(int a, int b)
{
  int buf;
  buf = a;
  a = b;
  b = buf;
}

関数の定義で記述された引数は「仮引数」と呼ばれ、その関数の定義内でのみ通用する自動変数です。

swap(x, y);
のように呼び出したとき、呼び出し側がswap関数に渡す引数(実引数)は『変数xとyの持つ値』であって、変数xとyが示す入れ物そのものではありません。

swap関数の受け取ったxとyの持つ値はswap関数内の自動変数aとbにコピーされて処理が行われます。そのため関数内で2つの値は入れ替わりますが、この変数aとbはswap関数の処理が終わって呼び出し元に戻るときには消滅しています。