ブロックと変数の有効範囲

複数の実行文を一まとまりとして考える方法と、変数の有効範囲について。
サイト全体の目次

稿


稿

ブロックと変数の有効範囲1

このセクションのソース

/*01*/ #include <stdio.h>
/*02*/ 
/*03*/ main()
/*04*/ {
/*05*/   {
/*06*/     int x = 10;
/*07*/     int y = 20;
/*08*/     int z = x + y;
/*09*/     printf("%d + %d = %d\n", x, y, z);
/*10*/   }
/*11*/ 
/*12*/   {
/*13*/     int x = 15;
/*14*/     int y = 25;
/*15*/     int z = x + y;
/*16*/     printf("%d + %d = %d\n", x, y, z);
/*17*/   }
/*18*/ 
/*19*/   return 0;
/*20*/ }

list-1.6.1-05

これまでの内容ではあまり意味がないのですが、「{ }」で複数の実行文をくくると、あたかも一つの実行文であるかのように扱うことができます。つまり、05行目から10行目までは

x に 10 を代入する。
y に 20 を代入する。
z に x + y を代入する。
x + y = z を表示する。

ではなく、プログラム上の意味としては
x に 10 を代入して y に 20 を代入して z に x + y を代入して x + y = z を表示する。

なのです。12行目から17行目までも同様です。そして、この「{ }」でくくられた部分をブロックと言います。

さて、変数はブロックごとに宣言することができ、そのブロック内でのみ、効力を発揮します。従って、

int x = 10;
int y = 20;
int z = x + y;

int x = 15;
int y = 25;
int z = x + y;

printf("%d + %d = %d\n", x, y, z);
printf("%d + %d = %d\n", x, y, z);

は同じブロック内に同じ名前の変数があるためエラーとなりますが、list-1.6.1 のようにブロックごとに変数を作ればエラーになりません。なお、変数は各ブロックの先頭で宣言する必要があります。ただし、C99 ではブロック内のどこで宣言してもかまいません。

ブロックと変数の有効範囲2

このセクションのソース

/*01*/ #include <stdio.h>
/*02*/ 
/*03*/ main()
/*04*/ {
/*05*/   int x = 10;
/*06*/   int y = 20;
/*07*/   int z = x + y;
/*08*/   int xyz;
/*09*/ 
/*10*/   {
/*11*/     int x = 15;
/*12*/     int y = 25;
/*13*/     int z = x + y;
/*14*/     int xy = x * y;
/*15*/     xyz = x * y * z;
/*16*/     printf("%d + %d = %d\n", x, y, z);
/*17*/     printf("%d * %d = %d\n", x, y, xy);
/*18*/     printf("%d * %d * %d = %d\n", x, y, z, xyz);
/*19*/   }
/*20*/ 
/*21*/   printf("%d + %d = %d\n", x, y, z);
/*22*/   printf("%d * %d * %d = %d\n", x, y, z, xyz);
/*23*/ 
/*24*/   return 0;
/*25*/ }

(untitled)

すでにお気づきかもしれませんが、ブロックの中にブロックを含めることができます。list-1.6.1 や list-1.6.2 は main 関数全体のブロックの中にブロックを作成しています。もちろん、その中へさらにブロックを作ることができます。このように、ブロックの中にブロックを含めることをネスト(入れ子)と言います。

基本的に、外側のブロックで宣言された変数は内側でも有効です。従って、08行目で宣言された xyz と 15行目の xyz は同じものです。では、外側のブロックで宣言された変数と同じ名前の変数が内側のブロックでも宣言されたらどうなるのでしょうか。この場合、内側のブロックでは外側のブロックが無視されます。従って05、06、07行目の x、y、z と11、12、13行目の x、y、z は別物です。そのため、xyz の結果は内側のブロックの x、y、z により計算された値が代入されることになります。逆に、内側のブロックで宣言された変数をその外で使用することはできません。例えば14行目の xy を内側のブロックの外で使用するとエラーになります。

(untitled)

(untitled)

以上のように、変数にはブロックで区切られた有効範囲があります。この有効範囲のことを変数のスコープまたは有効範囲と言います。