C言語の関数に関連するスコープ規則をわかりやすく解説
スコープ(有効範囲)とは
C言語におけるスコープ(Scope:有効範囲)は、次の3つの要素と密接な関係があります。
- 変数へのアクセス可能性 ― どの関数から参照・操作できるか
- 変数の存在期間(寿命) ― 変数がメモリ上に保持される期間
- 変数の使用範囲(境界) ― コードのどの部分で利用できるか
関数に関連するスコープ規則
- 関数とは、特定の処理を実行するための自己完結型のブロックです。
- 関数本体の内部で宣言された変数はローカル変数(局所変数)と呼ばれます。
- ローカル変数は、それを宣言した関数の中でのみ存在し、他の関数やmain関数からも参照できません。
- ローカル変数の寿命は、関数が処理を完了して呼び出し元へ戻った時点で終了します。
例1:ローカル変数を使った場合
以下は、関数に関連するスコープ規則を確認できるC言語プログラムです。
#include <stdio.h>
main() {
int a = 10, b = 20;
printf("before swapping a=%d, b=%d\n", a, b);
swap(a, b);
printf("after swapping a=%d, b=%d\n", a, b);
}
swap(int a, int b) {
int c;
c = a;
a = b;
b = c;
}
実行結果
before swapping a=10, b=20 after swapping a=10, b=20
注目すべきは、swap関数を呼び出してもaとbの値が入れ替わっていない点です。これは、swap関数の引数a・bがローカル変数であり、main関数のa・bとはまったく別のメモリ領域を持つためです。C言語では引数が「値渡し(Call by Value)」で渡されるため、関数内での変更は呼び出し元に一切影響しません。
グローバル変数のスコープ
- 関数本体の外部で宣言された変数はグローバル変数(大域変数)と呼ばれます。
- グローバル変数は、プログラム内のどの関数からでもアクセスできます。
例2:グローバル変数を使った場合
続いて、グローバル変数を使用した場合のプログラムを見てみましょう。
#include <stdio.h>
int a = 10, b = 20;
main() {
printf("before swapping a=%d, b=%d\n", a, b);
swap();
printf("after swapping a=%d, b=%d\n", a, b);
}
swap() {
int c;
c = a;
a = b;
b = c;
}
実行結果
before swapping a=10, b=20 after swapping a=20, b=10
今回は、aとbがグローバル変数として宣言されているため、swap関数内での変更がそのままmain関数にも反映され、値が正しく入れ替わっています。このように、変数をどこで宣言するかによってスコープ(有効範囲)とプログラムの動作が大きく変わるため、ローカル変数とグローバル変数の違いをしっかり理解しておくことが重要です。
-
C言語におけるユニオンとポインタの使い方を徹底解説
ユニオン(共用体)とは、異なるデータ型を持つ複数の変数が、同一のメモリ領域を共有するための仕組みです。構造体が各メンバーごとに独立したメモリを割り当てるのに対し、ユニオンではすべてのメンバーが同じアドレスを参照するという点が大きな特徴です。 ユニオンの構文 ユニオンを定義するときの基本的な書式は次の通りです。 union タグ名{ データ型 メンバー1; データ型 メンバー2; ---- ---- データ型 メンバーn; }; 実際の記述例を見てみましょう。 union sample{ int a; float b; char
-
C言語のポインタ入門!宣言・初期化から配列アクセスの実例まで徹底解説
ポインタ(pointer)とは、他の変数のメモリアドレスを格納するための変数です。C言語においてポインタは、メモリを直接操作したり、関数間でデータを効率的にやり取りしたりするために欠かせない重要な概念です。 ポインタの宣言・初期化とアクセス まず、次のような通常の整数変数の宣言を見てみましょう。 int qty = 179; 変数qtyには値「179」が格納されると同時に、メモリ上のどこかにその格納場所(アドレス)が割り当てられます。 ポインタの宣言 int *p; 「p」はポインタ変数であり、別の整数型(int)変数のアドレスを保持します。変数名の前にアスタリスク(*)を付けることで、「こ