トラック7・🧩関数とスコープ

変数の寿命とstatic

読む目安 約12分・ゴール:自動変数とstatic変数の寿命の違いを説明でき、使い分けられる

アプリでこのトピックを学ぶ(無料・登録不要)

このトピックの要点

前のトピックが「どこから見えるか」の話なら、今回は「いつまで生きているか」の話です。この2つは似ていますが別物で、混ぜて考えると必ずつまずきます。

ふつうの局所変数は自動変数と呼ばれ、宣言された瞬間に生まれ、ブロックを抜けると消えます。関数を呼ぶたびに新品が用意されるので、前回の値は残っていません。使い捨てのメモ用紙のようなものです。

ところが、関数の中に置いたまま値を残したいことがあります。そこで使うのが static です。

#include <stdio.h>

int counter(void)
{
    static int count = 0;   // 最初の1回だけ初期化される
    count++;
    return count;
}

int main(void)
{
    printf("%d\n", counter());   // 1
    printf("%d\n", counter());   // 2
    printf("%d\n", counter());   // 3
    return 0;
}

static int count = 0; の初期化はプログラム開始時に一度だけ行われ、関数を抜けても count は消えません。次に呼ばれたとき、前回の値の続きから始まります。ノートを引き出しにしまっておくイメージです。

大事なのは、static を付けてもスコープは広がらないことです。count は相変わらず counter の中からしか見えません。変わるのは寿命だけ。「見える範囲は狭いまま、寿命だけ長い」——これが static 局所変数の正体です。

初期化のルールの違い

void f(void)
{
    int a;            // 中身は不定(ゴミ)。使う前に必ず代入する
    static int b;     // 自動的に 0 で初期化される
    printf("%d\n", b);
}

自動変数は初期化を書かなければ中身が不定ですが、static 変数は必ず 0 から始まります。この差は覚えておくと事故を防げます。

どこに置かれているのか

自動変数は関数を呼ぶたびにスタック上の作業台に作られ、抜けるときに丸ごと片づけられます。一方 static 変数は、プログラム開始時に別の場所(静的領域)へ一度だけ確保されます。置き場所が違うから寿命も違う、というわけです。メモリのどこに何が置かれるかは、第2部で地図にして詳しく見ます。

使いどころの例

いずれも「その関数だけが知っていればよい情報」です。同じことをグローバル変数でやると誰からでも触れてしまうので、static 局所変数のほうが安全です。

罠・注意

ビットスコープは「どこから見えるか」、寿命は「いつまで生きているか」。別の話だよ

まとめ: 自動変数は使い捨て、static 変数は据え置き。static は寿命だけを延ばす道具で、見える範囲は変わりません。

アプリでこのトピックを学ぶ(無料・登録不要)

確認問題

確認問題 1

関数の中に書いた static int count = 0; の説明として正しいものはどれですか。

  1. 関数を呼ぶたびに 0 に戻る
  2. 初期化は最初の1回だけで、値は次の呼び出しにも残る
  3. 他の関数からも count という名前で使える
  4. プログラム終了時に自動で 0 に戻る
答えを見る

正解:B(初期化は最初の1回だけで、値は次の呼び出しにも残る)

static 局所変数は初期化が一度きりで、関数を抜けても値が残ります。ただし変わるのは寿命だけで、スコープはその関数の中のままです。他の関数からは見えません。

確認問題 2

次のプログラムの出力はどれですか。

#include <stdio.h>

int counter(void)
{
    static int count = 0;
    count++;
    return count;
}

int main(void)
{
    printf("%d ", counter());
    printf("%d ", counter());
    printf("%d\n", counter());
    return 0;
}
  1. 1 1 1
  2. 1 2 3
  3. 0 1 2
  4. 3 3 3
答えを見る

正解:B(1 2 3)

static のおかげで count は呼び出し間で保持され、1・2・3 と増えていきます。static を外すと毎回新しい count が 0 から作られ、出力は 1 1 1 になります。

「関数とスコープ」の目次

  1. 関数とは——処理に名前を付ける
  2. 引数と戻り値
  3. プロトタイプ宣言
  4. 変数のスコープ——見える範囲
  5. 変数の寿命とstatic
  6. コールスタック——関数呼び出しの舞台裏
  7. 値渡しの本質
  8. グローバル変数との付き合い方
  9. 関数分割の設計センス
  10. 再帰の入口——自分を呼ぶ関数

もっと先へ:ポインタ・メモリ・ファイル入出力・セキュアコーディングを含む全26トラックと、段位検定・模試のフルセットは完全版に収録しています。

完全版の販売ページは準備中です。

ほかのトラック

📚 姉妹教材:手を動かして覚える Linux 教材 — Linuxとインフラの仕組みを地図で学ぶ

Web版