C言語で変数を宣言するとき、その変数がプログラムの**「どこからどこまで使えるか」という有効範囲が決まっています。この有効範囲のことをスコープ**と呼びます。
スコープを正しく理解しないと、「使えるはずの変数にアクセスできない」「意図しない場所で変数の値が変わってしまった」といったバグの原因になります。
今回は、C言語における最も基本的なスコープである**「ローカル変数」と「グローバル変数」**の違いと、それぞれの適切な使い方について解説します。
ローカル変数:関数内でのみ有効な変数
ローカル変数とは、関数やブロック{}
の内部で宣言された変数のことです。
** analogy:** ローカル変数は、**「特定の作業のためだけに使う道具箱」**のようなものです。その作業(関数)が始まったときに用意され、作業が終わると片付けられます。他の作業場から、その道具箱の中身を勝手に使われることはありません。
ローカル変数の特徴
- スコープが限定的: 宣言された関数やブロック
{}
の中でしかアクセスできません。 - 独立している: 他の関数で同じ名前のローカル変数を宣言しても、それらは全くの別物として扱われます。
- 安全性が高い: スコープが狭いため、意図しない場所から値を変更される心配がなく、安全でバグの少ないプログラムを書きやすくなります。
サンプルコード
main
関数とanother_function
の両方でlocal_counter
という同じ名前の変数を宣言しても、互いに干渉しないことを確認してみましょう。
#include <stdio.h>
void another_function(void) {
int local_counter = 100; // another_function専用のローカル変数
printf("another_function内のlocal_counter: %d\n", local_counter);
local_counter += 50; // こちらの変数を変更してもmainには影響しない
printf("another_function内で変更後: %d\n", local_counter);
}
int main(void) {
int local_counter = 10; // main関数専用のローカル変数
printf("main内のlocal_counter: %d\n", local_counter);
another_function();
printf("another_function呼び出し後のmainのlocal_counter: %d\n", local_counter);
return 0;
}
実行結果:
main内のlocal_counter: 10
another_function内のlocal_counter: 100
another_function内で変更後: 150
another_function呼び出し後のmainのlocal_counter: 10
another_function
内でlocal_counter
の値を変更しても、main
関数のlocal_counter
は10
のまま変わっていません。これがローカル変数の大きなメリットです。
グローバル変数:プログラム全体で有効な変数
グローバル変数とは、どの関数の外側でもなく、プログラムのトップレベルで宣言された変数のことです。
** analogy:** グローバル変数は、**「街の掲示板」**のようなものです。街の誰でも(プログラムのどの関数からでも)その掲示板を見たり、内容を書き換えたりすることができます。
グローバル変数の特徴
- 広いスコープ: プログラムのどこからでもアクセスし、値を読み書きできます。
- データ共有が容易: 複数の関数で同じデータを共有したい場合に便利です。
サンプルコード
ゲームの難易度設定のように、プログラム全体で共有したい情報にグローバル変数を使ってみましょう。
#include <stdio.h>
// g_はglobalの意。グローバル変数だと分かりやすくする命名規則の一つ
double g_tax_rate = 0.1; // 消費税率をグローバル変数として定義
// 税込み価格を計算する関数
double calculate_with_tax(int price) {
// グローバル変数 g_tax_rate を参照
return price * (1.0 + g_tax_rate);
}
int main(void) {
int price;
printf("商品の価格を入力してください: ");
scanf("%d", &price);
double total_price = calculate_with_tax(price);
// main関数からもグローバル変数を参照
printf("価格 %d円 の税込価格は %.0f円です。(消費税率%.2f)\n", price, total_price, g_tax_rate);
return 0;
}
グローバル変数の乱用に注意!
グローバル変数はどこからでもアクセスできて便利な反面、現代のプログラミングでは多用すべきではないとされています。
- バグの温床になりやすい: プログラムのどこからでも値を変更できるため、「いつ、どこで、誰が値を変更したのか」が分かりにくくなり、バグの追跡が非常に困難になります。
- コードが読みにくくなる: 関数がグローバル変数に依存していると、コードの関連性が複雑になり、プログラム全体の把握が難しくなります。
基本的な考え方として、変数はできるだけ狭いスコープ、つまりローカル変数として宣言し、関数間でデータを受け渡す場合は引数や戻り値を使うのが推奨されます。
まとめ
ローカル変数 | グローバル変数 | |
宣言場所 | 関数やブロック{} の内側 | 全ての関数の外側 |
有効範囲 | 宣言された場所の中だけ | プログラムのどこからでも |
メリット | 安全性が高く、他の部分に影響を与えない | データの共有が簡単 |
デメリット | 他の関数とデータを共有するには工夫が必要 | 意図しない変更が起こりやすく、バグの原因になりやすい |
変数のスコープを正しく理解し、適切に使い分けることで、より安全でメンテナンス性の高いプログラムを書くことができます。まずは**「変数は基本的にローカル変数として宣言する」**という習慣を身につけましょう。