C言語のグローバル変数とは?ローカル変数との違いと注意点を解説

目次

はじめに

C言語では、変数を関数の外で宣言できます。

例えば:

C
int g_count = 0;

このような変数を、「グローバル変数」と呼びます。

グローバル変数は便利な一方で、

  • どこからでも変更できる
  • バグ原因になりやすい
  • 設計が複雑になりやすい

という特徴もあります。

初心者のうちは、

  • ローカル変数と何が違う?
  • なぜ危険と言われる?
  • 組み込みでは使うの?
  • staticとの違いは?

が分かりにくいポイントです。

この記事では、C言語のグローバル変数について、

  • 基本的な仕組み
  • ローカル変数との違い
  • スコープ
  • 生存期間
  • 注意点
  • 実務での考え方

まで、初心者向けに分かりやすく解説します。


C言語文法解説シリーズ

本記事は「C言語文法解説シリーズ」の1つです。
C言語の文法を、組み込み開発の視点も交えて解説しています。

C言語文法解説シリーズ一覧はこちら

C言語の文法を基礎から体系的に解説するシリーズです。


グローバル変数とは?

グローバル変数とは、「関数の外で宣言される変数」です。

例えば:

C
#include <stdio.h>

int g_count = 0;

void func(void) {
    g_count++;
}

int main(void) {
    func();

    printf("%d\n", g_count);

    return 0;
}

なぜ「グローバル」なの?

これは、「複数の関数から使える」からです。

例えば:

C
int value = 100;

void funcA(void) {
    value++;
}

void funcB(void) {
    value--;
}

この value は、

  • funcA()
  • funcB()

の両方から使えます。

変数が見える範囲、つまりスコープについてはこちらの記事で解説しています。


ローカル変数との違い

宣言場所

グローバル変数

C
int x = 10;

のように関数外で宣言されます。

ローカル変数

C
void func(void) {
    int x = 10;
}

のように関数内で宣言されます。



生存期間

グローバル変数

プログラム開始から終了まで存在します。

つまり、main()開始前に生成し、
プログラム終了まで保持されます。

ローカル変数

一方でローカル変数は、関数終了と同時に消えます。

このように変数には「いつ生成され、いつ消えるのか」
という概念があります。

これを、記憶域期間(Storage Duration)と呼びます。

ローカル変数を含む記憶域期間についてはこちらの記事で解説しています。


初期化

グローバル変数

C
int g_value;

これは明示的に初期化しなくても、0で初期化されます。

ローカル変数

C
int x;

printf("%d\n", x);

ローカル変数は自動で0初期化されません。

そのため、不定値(ゴミ値)になる場合があります。

保存領域

グローバル変数はどこに置かれる?

通常、グローバル変数は:

  • .data領域 :初期値あり(ROMに保存 → 起動時にRAMへコピー)
  • .bss領域: 初期値なし(起動時にゼロクリア)

に配置されます。

例えば:

C
int x = 10;

.data領域

C
int y;

.bss領域

に置かれることが多いです。

.data領域.bss領域についてはこちらの記事で解説しています。


ローカル変数はどこに保存される?

通常、ローカル変数はスタック領域に保存されます。

例えば関数呼び出し時に、スタックに変数用メモリ確保が行われます。

関数終了時には、その領域が解放されます。

スタック領域についてはこちらの記事で解説しています。

比較表

項目ローカル変数グローバル変数
宣言場所関数内関数外
スコープブロック内複数関数
生存期間関数実行中のみプログラム終了まで
初期化0で初期化自動で0初期化されない
主な領域スタックdata/bss

ローカル変数についてはこちらの記事で解説しています。

staticを付けると?

例えば:

C
static int g_value;

とすると、「このファイル内だけで使える」
ようになります。

つまり:

種類参照範囲
通常グローバル他ファイルから参照可能
staticグローバルファイル内限定

となります。

staticや公開範囲を制限する効果についてはこちらの記事で解説しています。


externを付けると?

他ファイルのグローバル変数を使う場合:

C
extern int g_value;

のように宣言します。

これは「別ファイルに実体があります」という意味です。

externは別記事で詳しく解説しています。


なぜグローバル変数は危険と言われるの?

グローバル変数は便利ですが、「どこからでも変更できる」
という問題があります。


例えばこんなコード

C
int g_value = 0;

void funcA(void) {
    g_value = 100;
}

void funcB(void) {
    g_value = -1;
}

この場合、誰が値を変更したのか
が分かりにくくなります。


規模が大きいと危険

小さいコードでは問題ありません。

しかし大規模開発では:

  • 予期しない変更
  • 状態依存
  • デバッグ困難
  • 影響範囲拡大

が起きやすくなります。


「隠れた依存」が発生する

例えば:

C
void func(void) {
    if (g_mode == 1) {
        process();
    }
}

この関数は、g_mode に依存しています。

しかし引数に現れないため、何に依存しているか見えにくい
という問題があります。


組み込みでは普通に使われる

「グローバル変数は悪!」

と単純には言えません。

組み込みでは:

  • 状態管理
  • 割り込み共有
  • ハードウェア状態
  • RTOSフラグ

などで普通に使われます。


ただし設計ルールが重要

例えば:

  • 必要最小限にする
  • staticで公開範囲を制限
  • externを乱用しない
  • アクセス関数を作る

などの工夫をします。


グローバル変数の注意点

① 変更箇所が追いにくい

どこからでも変更できるため、値がいつ変わったか分かりにくい
ことがあります。


② バグが広がりやすい

1つの変数変更が、

複数機能へ影響する場合があります。


③ テストしにくい

前回状態が残るため、テストが独立しにくい
ことがあります。


④ 割り込みやマルチスレッドで危険

複数箇所から同時アクセスされると:

  • 競合
  • race condition
  • 不整合

が起きる場合があります。


「必要な範囲だけ使う」が基本

C言語では、「変数は必要最小限の範囲で使う」
のが基本です。

そのため通常はローカル変数優先
で設計します。

グローバル変数は、本当に共有が必要な場合
に使います。


まとめ

グローバル変数とは、「関数外で宣言され、複数関数から使える変数」です。

特徴を整理すると:

  • プログラム終了まで存在
  • data/bss領域に配置
  • どこからでもアクセス可能
  • 便利だが依存が増えやすい

となります。

組み込み開発では非常によく使われますが、「公開範囲を最小限にする」
ことが重要です。

この記事が参考になった方へ

スコープを含むC言語の基本文法をこちらの記事で整理しています。

エンジニアとして技術を学ぶことは重要ですが、
キャリアや副業についても同時に考える必要があります。

副業の現実や市場価値、今後のキャリア戦略については、
こちらの記事でまとめています。

技術に関するご相談・開発・自動化ツール作成・記事執筆などのご依頼も承っています。

小さなご相談からでもお気軽にご連絡ください。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

組み込みソフトエンジニアとして働きながら、
C言語・メモリ・ポインタなどの基礎から実務まで解説しています。

副業・キャリアについても実体験ベースで発信中です。

X・Qiita・noteでも発信しています。
X:更新情報・日常
Qiita:技術発信
note:キャリア・副業

▼まずはここから読むのがおすすめ
C言語文法シリーズ
メモリ領域解説シリーズ
割り込み処理解説シリーズ
ソフトウェア設計解説シリーズ
キャリアと副業ロードマップ

コメント

コメントする


目次