問題の背景:
C言語では、メモリ管理とコードの可視性の制御のために、グローバル変数とローカル変数が導入されました。グローバル変数は、モジュラープログラミングが登場する前の関数間のデータ交換の主要な方法でしたが、ローカル変数は相互作用を減らし、コードの隔離を促進しました。
問題:
グローバル変数とローカル変数の違い、すなわち寿命、スコープ(可視性)、初期化のルールとタイミングについての誤解がしばしば生じます。グローバル変数は同期の問題や可読性の低下を引き起こし、ローカル変数は必要なデータにアクセスできなくなることがあります。これらの違いに対する理解の誤りはバグを引き起こし、コードのスケーラビリティを難しくします。
解決策:
グローバル変数はすべての関数の外部で宣言され、externを使用することで全ファイルからアクセス可能です。その寿命はプログラム全体であり、初期化は静的変数の場合は暗黙的にゼロで行われ、ユーザーの指定値で明示的に行います。ローカル変数は関数内で宣言され、その寿命は関数の呼び出しに限られ、自動的に初期化されることはありません。
コードの例:
int g_var = 42; // グローバル変数 void foo() { int l_var = 5; // ローカル変数 }
主な特徴:
ローカル変数は初期値が指定されていない場合、自動的にゼロで初期化されますか?
いいえ。グローバル変数や静的変数だけがデフォルトでゼロで初期化されます。ローカル変数は、明示的に初期値を与えない限り、「ゴミ」(不定値)を含みます。
例:
void test() { int a; printf("%d ", a); // 未定義の動作 }
異なるファイルから常にグローバル変数にアクセスできますか?
いいえ。関数の外でstaticとして宣言された変数は、そのソースファイル内でのみ見えます。グローバルな可視性が必要な場合はexternを使用してください。
関数内でグローバル変数を宣言することはできますか?
いいえ。関数内のすべての宣言はローカルです。グローバル変数は関数の外でのみ作成できます。
グローバル変数を使用して関数間でデータを交換します:
int error_code; void f1() { error_code = 1; } void f2() { if (error_code) ... }
利点:
欠点:
すべての変数がローカルで、データは関数のパラメータを介して渡されます:
void f1(int *err) { *err = 1; } void f2(int err) { if (err) ... }
利点:
欠点: