26 変数のスコープ

変数が「どこからどこまで使えるか」をスコープと呼ぶ。
関数を使い始めると、変数のスコープを意識しないとバグの原因になる。


26-1 ローカル変数

関数の中で宣言された変数はローカル変数(局所変数)と呼ぶ。
その関数の中だけで有効で、関数が終わると消える。

26_01_localScope.c
#include <stdio.h>

void show(void)
{
    int x = 10;                  /* show の中だけで有効 */
    printf("show の x = %d\n", x);
}

int main(void)
{
    int x = 5;                   /* main の中だけで有効 */
    printf("main の x = %d\n", x);
    show();
    printf("main の x = %d\n", x);  /* show を呼んでも変わらない */
    return 0;
}
main の x = 5
show の x = 10
main の x = 5
✅ main の x と show の x は名前が同じでも別々の変数
どちらの変更ももう片方には影響しない。

26-2 グローバル変数

関数の外(ファイルの先頭付近)で宣言された変数はグローバル変数(大域変数)と呼ぶ。
すべての関数からアクセスできる。

26_02_globalScope.c
#include <stdio.h>

int count = 0;   /* グローバル変数 */

void increment(void)
{
    count++;     /* グローバル変数を変更できる */
}

int main(void)
{
    printf("count = %d\n", count);  /* 0 */
    increment();
    printf("count = %d\n", count);  /* 1 */
    increment();
    printf("count = %d\n", count);  /* 2 */
    return 0;
}
count = 0
count = 1
count = 2
⚠ グローバル変数はどこからでも変更できるため、意図しない変更によるバグが起きやすい
特に必要な場合以外はローカル変数を使うことが推奨される。

26-3 同じ名前のローカルとグローバル

同じ名前の変数がローカルとグローバルに存在する場合、
関数内ではローカル変数が優先される(グローバルは隠れる)。

26_03_scopePriority.c
#include <stdio.h>

int value = 100;   /* グローバル */

int main(void)
{
    int value = 50;                  /* ローカル(グローバルを隠す) */
    printf("value = %d\n", value);   /* 50 が表示される */
    return 0;
}
value = 50
⚠ 同じ名前のローカルとグローバルが混在するコードは読みにくい。
変数名が重複しないよう命名することを推奨する。

26-4 ローカルとグローバルの比較

ローカル変数グローバル変数
宣言場所関数の中関数の外(ファイル先頭)
有効範囲宣言した関数内のみプログラム全体
生存期間関数が実行される間だけプログラム全体
初期値不定(初期化が必要)0 で自動初期化
推奨✅ 基本はこちら⚠ 必要な場合のみ

26-5 演習

📝 演習① グローバルカウンター

グローバル変数 count を使い、関数 call() を呼ぶたびに
「呼び出し回数: N」と表示するプログラムを作れ。main から3回呼ぶこと。

26_04_counter.c
#include <stdio.h>

/* ここにグローバル変数を宣言する */

void call(void)
{
    /* ここを書く */
}

int main(void)
{
    call();
    call();
    call();
    return 0;
}
答えの例を表示
#include <stdio.h>

int count = 0;

void call(void)
{
    count++;
    printf("呼び出し回数: %d\n", count);
}

int main(void)
{
    call();
    call();
    call();
    return 0;
}

26-6 理解度チェック

Q1. 次のプログラムの出力として正しいものはどれか。

#include <stdio.h>
int num = 10;
void func(void)
{
    int num = 5;
    printf("A: %d\n", num);
}
int main(void)
{
    printf("B: %d\n", num);
    func();
    printf("C: %d\n", num);
    return 0;
}
▶ トレース表を見る
実行箇所参照する num出力
main: printf("B: %d\n", num)グローバル num = 10B: 10
func: printf("A: %d\n", num)ローカル num = 5A: 5
main: printf("C: %d\n", num)グローバル num = 10C: 10
解説を表示

正解:イ

main の printf("B:") と printf("C:") はグローバル num=10 を参照。
func 内では同名のローカル num=5 が優先される。

Q2. 次のプログラムの出力として正しいものはどれか。

#include <stdio.h>
void test(void)
{
    int x = 2;
    printf("x = %d\n", x);
}
int main(void)
{
    int x = 5;
    test();
    printf("x = %d\n", x);
    return 0;
}
解説を表示

正解:イ

test() の x と main の x は別物。test() を呼んでも main の x=5 は変わらない。

Q3. ローカル変数の説明として正しいものはどれか。

解説を表示

正解:ウ

ローカル変数はその関数内だけで有効。初期化されないと不定値(ゴミ値)になる点に注意。

Q4. グローバル変数の使用が推奨されない主な理由はどれか。

解説を表示

正解:イ

グローバル変数はどの関数からでも変更できるため、予期しない変更によるバグが追いにくくなる。