C言語 グローバル変数の“ひとまとめ管理”テクニック
— extern
の乱立を防ぎ、追加・削除をラクにする —
複数の .c
ファイルで同じグローバル変数を使うとき、
毎回 extern
宣言を書いたり、実体定義の場所を探したり…たしかに面倒ですよね。
そこで 「ヘッダ 1 枚で定義と参照を切り替える」 スマートな方法をご紹介します。
🔧 キーアイデア
ポイント | 説明 |
---|---|
実体は常に 1 か所だけ | 多重定義リンカエラーを防止 |
他ファイルは extern 参照 |
変数名がブレず安全 |
追加・削除が超簡単 | ヘッダ 1 枚を書き換えるだけ |
1. 共通ヘッダ sample.h
#ifndef _SAMPLE_H_
#define _SAMPLE_H_
/* ── 定義 or 参照を切り替えるマクロ ────────────── */
#ifdef __MAIN_EXTERN__ /* 実体を作る側で定義 */
#define EXTERN /* 実体定義 (空) */
#else
#define EXTERN extern /* 参照宣言 */
#endif
/* ─────────────────────────────────── */
EXTERN int g_nData;
EXTERN int g_nList;
#endif /* _SAMPLE_H_ */
EXTERN マクロが “定義” と “参照” の両方を兼ねるのがポイント。
MAIN_EXTERN を立てるかどうかで自動切り替え!
2.実体を持つファイル sample1.c
#define __MAIN_EXTERN__ /* ← 実体を生成する宣言 */
#include "sample.h"
void funcA(void) {
g_nData++;
g_nList++;
}
・MAIN_EXTERN を 定義してからヘッダを読み込む
・これにより g_nData, g_nList の 実体がここで 1 回だけ生成される
3.参照オンリーのファイル sample2.c
#include "sample.h" /* 参照側はこれだけ! */
void funcB(void) {
g_nData++;
g_nList++;
}
・MAIN_EXTERN を立てていないので EXTERN は extern となり、
・ヘッダ内は 単なる宣言 として扱われる
💡 まとめ & メリット
・定義と参照が 1 枚のヘッダで完結 → 追跡がラク
・追加・削除が簡単
→ 新しい変数は sample.h に 1 行追加するだけ
・extern の書き忘れや多重定義の心配を防げる
・テスト用に スタブ変数 を差し替えるときも同じパターンで応用可
Tip : プロジェクトで変数が増えたら「モジュールごとにヘッダを分割」→
__<MODULE>_EXTERN__マクロを使うと管理がさらにスッキリします。