🇯🇵 日本語 | 🇺🇸 English

第29回 グローバル変数

C言語のグローバル変数・スコープ・変数の寿命・static変数を解説。

📖 このページで覚えること
✅ 最低限ここだけ覚える
  • 関数の外で宣言するとグローバル
  • 全関数から読み書きできる
  • ローカル変数と同名なら内側が優先
⭐ 余裕があれば読む
  • static でファイル外から隠す
  • extern で別ファイルから参照
  • グローバル変数の濫用は避ける

スコープ ― 変数が使える範囲

変数が参照できる範囲(スコープ)は宣言した場所で決まります。
int main(void) {
  int a = 10;          // main内で有効
  if (a > 0) {
    int b = 20;        // このブロック内だけで有効
    printf("%d\n", a+b); // OK
  }
  // printf("%d\n", b);  ← エラー!bはスコープ外
}
ローカル変数
関数・ブロック内でのみ有効。抜けると消える
グローバル変数
関数の外で宣言。どこからでも使える
static変数
関数内でも値を保持し続けるローカル変数

変数の寿命 ― いつ生まれ、いつ消えるか

スコープは「どこから見えるか」でしたが、寿命(lifetime)は変数がメモリ上にいつ確保され、いつ解放されるかを指します。

3種類の寿命

種類宣言場所生成タイミング消滅タイミング
auto(ローカル)関数・ブロック内ブロックに入ったときブロックを抜けたとき
グローバル関数の外プログラム開始時プログラム終了時
static関数内(static付き)プログラム開始時プログラム終了時
void example(void) {
  int        a = 1;   // auto: 呼ぶたびに生成→抜けると消滅
  static int b = 1;   // static: 一度だけ生成。値は次回も残る
  a++; b++;
  printf("a=%d b=%d\n", a, b);
}
int main(void) {
  example();  // a=2 b=2
  example();  // a=2 b=3  ← aはリセット、bは保持
  example();  // a=2 b=4
}

寿命を可視化してみよう

ボタンを押すと、example() を3回呼んだときに各変数がどう変化するかアニメーションで確認できます。
ステップ 0 / 9
コール状態
メモリ上の変数
出力

グローバル変数 ― 全関数で共有

#include<stdio.h>

int counter = 0;        // グローバル変数(main等の外)

void increment(void) {
  counter++;            // 引数なしでも触れる
}

int main(void) {
  increment();
  increment();
  increment();
  printf("%d\n", counter); // → 3
}
使いすぎ注意: グローバル変数は便利ですが、どこで変更されているか追いづらいためバグの原因になりがち。必要最小限に。

static変数 ― 関数内で値を保持

通常のローカル変数は関数を抜けると消えますが、staticをつけるとプログラム終了まで残ります
void count(void) {
  static int n = 0;  // 初回のみ0で初期化。以降は保持
  n++;
  printf("呼ばれた回数: %d\n", n);
}

int main(void) {
  count();  // → 1
  count();  // → 2
  count();  // → 3
}
使い所: 「関数が何回呼ばれたか」や「前回の結果を覚えておきたい」とき。グローバル変数を避けたいが状態は欲しいという場面で便利。

メモリ上の配置 ― 変数はどこに格納される?

ローカル変数・グローバル変数・static変数は、メモリ上で別々の領域に配置されます。これがそれぞれの「寿命」の違いを生んでいます。

C言語プログラムのメモリマップ

C言語のプログラムが動作するとき、メモリは以下の5つの領域に分かれています。
高アドレス ↑
📚 スタック領域
ローカル変数・関数の引数・戻り先アドレス。
関数呼び出しごとに確保・解放(自動)。
↓ 伸びる方向 ↓
(未使用領域)
↑ 伸びる方向 ↑
🧱 ヒープ領域
malloc/freeで動的確保する領域。
プログラマが管理(明示的)。
🌐 BSS 領域(未初期化データ領域)
初期値なしのグローバル変数・static変数。
起動時に0で自動初期化
💾 データ領域(初期化済み)
初期値ありのグローバル変数・static変数。
プログラム終了まで存続。
📜 テキスト領域(コード領域)
プログラムの機械語コード・文字列リテラル。
読み取り専用。
低アドレス ↓

コードと領域の対応

#include <stdio.h>
#include <stdlib.h>

int g_init = 100;        // 💾 データ領域(初期値あり)
int g_uninit;            // 🌐 BSS領域(初期値なし → 自動的に0)

void func(void) {
    int local = 5;        // 📚 スタック領域(呼び出しごとに生成)
    static int s = 0;    // 💾 データ領域(1度だけ生成)
    int *heap = malloc(sizeof(int)); // 🧱 ヒープ領域
    *heap = 42;
    free(heap);
}

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

変数の種類と格納先まとめ

変数の種類宣言場所メモリ領域生成タイミング初期値
ローカル(auto) 関数内 📚 スタック 関数呼び出し時 不定(ゴミ値)
ローカル(static) 関数内(static付き) 💾 データ / BSS プログラム開始時 0 または指定値
グローバル(初期化あり) 関数の外 💾 データ領域 プログラム開始時 指定値
グローバル(初期化なし) 関数の外 🌐 BSS領域 プログラム開始時 0(自動)
malloc で確保 関数内で動的 🧱 ヒープ malloc呼び出し時 不定(callocなら0)
文字列リテラル ソース内の "..." 📜 テキスト プログラム開始時 書き換え不可

関数呼び出しとスタックの動き

関数を呼び出すたびに、スタックには「スタックフレーム」が積まれます。関数が終わると自動的に取り除かれます。
void b(void) { int y = 20; }  // b のスタックフレーム
void a(void) { int x = 10; b(); }  // a のスタックフレーム
int main(void) { a(); return 0; }
main → a() → b() と呼んだ時のスタック:
b() のフレーム(y=20)← 先頭(最後に積まれた)
a() のフレーム(x=10)
main() のフレーム
b() が終わると b のフレームが外れ、a に戻ると a のフレームも外れる。
スタックオーバーフローの正体: 関数を深く呼び出しすぎる(無限再帰など)と、スタック領域を使い切って Segmentation Fault が発生します。

「寿命」と「メモリ領域」の関係

短命 = スタック
ローカル変数。関数が終わると消える。速いが、関数を超えて保持できない。
長命 = データ/BSS
グローバル・static変数。プログラム終了まで存続。いつでもアクセス可能だが、使いすぎると保守性が下がる。
柔軟 = ヒープ
malloc で確保、free で解放。サイズも寿命も自分で管理。解放忘れ = メモリリーク。

自分で書いてみよう ― スコープ

scope.c
出力
「実行」を押してください...
💡 こんなことも試してみよう

関連する講座

関数編
第24回 関数(基本)
C言語の関数の定義と呼び出し。引数・戻り値の仕組みを図解。
入門編
第3回 変数
C言語の変数とは?int, double, charの使い方を図解で解説。
関数編
第28回 プロトタイプ・マクロ
C言語のプロトタイプ宣言と#defineマクロの使い方を解説。
← 前の講座
第28回 プロトタイプ・マクロ
次の講座 →
第30回 配列を引数に

確認クイズ

この講座の理解度をチェックしましょう!

Q1. グローバル変数の初期値(int型)は?

未定義
0
-1

グローバル変数は宣言時に自動的に 0 で初期化されます。ローカル変数は初期化しないと未定義値になります。

Q2. static 変数の特徴は?

関数を抜けても値が保持される
他のファイルからアクセスできる
実行速度が速くなる

static ローカル変数は関数を抜けても値が消えず、次回呼び出し時に前の値が残っています。

Q3. グローバル変数の多用が推奨されない理由は?

メモリを多く使うから
どこからでも変更できてバグの原因になるから
実行速度が遅くなるから

グローバル変数はプログラムのどこからでも変更可能なため、意図しない変更によるバグが発生しやすくなります。

この記事をシェア
X(Twitter)でシェア Facebookでシェア LINEで送る はてブ

この講座の理解を深めるおすすめ書籍

サイトで動きを理解し、書籍で演習量を補うと効果的です

📘
苦しんで覚えるC言語
MMGames 著
初心者向けの定番入門書。丁寧な解説で基礎を固められます。
Amazonで見る
📗
新・明解C言語 入門編
柴田望洋 著
図解が豊富で、演習問題も充実。大学の教科書としても採用多数。
Amazonで見る
📙
プログラミング言語C 第2版
B.W.カーニハン, D.M.リッチー 著
通称K&R。C言語の原典。基礎を終えた後のステップアップに最適。
Amazonで見る

※ 上記リンクはアフィリエイトリンクです。購入によりサイト運営を支援いただけます。