C言語のスコープ規則を解説!ステートメントブロックと変数の有効範囲
プログラミングにおけるスコープ(有効範囲)の規則は、主に以下の3つの要素と密接に関係しています。
- 変数へのアクセス可能性
- 変数が存在する期間(寿命)
- 変数を使用できる範囲の境界
ステートメントブロックに関連するスコープ規則の基本
- ブロックとは、波括弧 { } で囲まれた一連の文の集まりのことです。
- ブロック内で宣言された変数は、そのブロック内でのみアクセス・使用でき、ブロックの外側では存在しません。
ここからは、具体的なサンプルコードを使って、ブロックとスコープの関係を詳しく見ていきましょう。
例1:独立した2つのブロックで別々の変数を宣言する
以下は、ステートメントブロックに関連するスコープ規則を確認できるC言語のサンプルプログラムです。
#include<stdio.h>
main ( ){
{
int i = 1;
printf ("%d",i);
}
{
int j = 2;
printf("%d",j);
}
}実行結果
1 2
それぞれのブロック内で宣言された変数は、たとえ同じ名前で再宣言されていたとしても、互いにまったく別の変数として扱われます。
例2:同じ名前の変数を異なるブロックで宣言する
次に、同じ変数名 i を別々のブロックで宣言した場合の動作を確認してみましょう。
#include<stdio.h>
main ( ){
{
int i = 1;
printf ("%d",i);
}
{
int i = 2;
printf ("%d",i);
}
}実行結果
1 2
各ブロック内で同じ名前の変数を再宣言しても問題なく動作します。これは、ブロックごとに独立したスコープが生成されるためです。
例3:ネストしたブロックによる変数の隠蔽(シャドーイング)
外側のブロックと同じ名前の変数を内側のブロックで宣言すると、どうなるでしょうか。
#include<stdio.h>
main ( ){
int i = 1;
{
int i = 2;
printf ("%d",i);
}
}実行結果
2
このように、内側のブロックで外側と同じ名前の変数を宣言すると、内側のブロック実行中は外側の変数が隠される(マスクされる)という現象が起こります。これを「シャドーイング」と呼びます。
例4:内側のブロックから外側の変数へアクセスする
今度は、内側のブロックで同名の変数を宣言せずに、外側の変数へアクセスしてみます。
#include<stdio.h>
main ( ){
int i = 1;
{
int j = 2;
printf ("%d",j);
printf ("%d",i);
}
}実行結果
2 1
内側のブロックで宣言していない限り、ネストした内側のブロックからも外側で宣言された変数にアクセス可能です。つまり、スコープは内側から外側へと参照できますが、その逆はできません。
まとめ
- 波括弧 { } で囲まれた部分がブロックとなり、独立したスコープを持つ。
- ブロック内で宣言された変数は、そのブロックの外では存在しない。
- 内側のブロックで同名の変数を宣言すると、外側の変数は隠蔽される。
- 内側のブロックから外側の変数は参照できる(同名宣言がない場合)。
これらのスコープ規則を正しく理解することで、意図しない変数の衝突やバグを防ぎ、より安全で読みやすいC言語プログラムを書けるようになります。
-
C言語におけるユニオンとポインタの使い方を徹底解説
ユニオン(共用体)とは、異なるデータ型を持つ複数の変数が、同一のメモリ領域を共有するための仕組みです。構造体が各メンバーごとに独立したメモリを割り当てるのに対し、ユニオンではすべてのメンバーが同じアドレスを参照するという点が大きな特徴です。 ユニオンの構文 ユニオンを定義するときの基本的な書式は次の通りです。 union タグ名{ データ型 メンバー1; データ型 メンバー2; ---- ---- データ型 メンバーn; }; 実際の記述例を見てみましょう。 union sample{ int a; float b; char
-
C言語のポインタ入門!宣言・初期化から配列アクセスの実例まで徹底解説
ポインタ(pointer)とは、他の変数のメモリアドレスを格納するための変数です。C言語においてポインタは、メモリを直接操作したり、関数間でデータを効率的にやり取りしたりするために欠かせない重要な概念です。 ポインタの宣言・初期化とアクセス まず、次のような通常の整数変数の宣言を見てみましょう。 int qty = 179; 変数qtyには値「179」が格納されると同時に、メモリ上のどこかにその格納場所(アドレス)が割り当てられます。 ポインタの宣言 int *p; 「p」はポインタ変数であり、別の整数型(int)変数のアドレスを保持します。変数名の前にアスタリスク(*)を付けることで、「こ