例1
単一ファイルで変数を共有したいときは、関数の外で宣言します。
これによって変数var
のスコープはこのmain.c
ファイル全体となります。
//main.c #include <stdio.h> int var; int func() { var += 1; return 0; } int main() { var = 2; func(); printf("%d", var); // 3 return 0; }
例2
次に、変数を複数のファイルで共有したい場合があると、以下のように書きたくなります。
//main.c #include <stdio.h> #include "sub.c" int var1; int func() { var1 += 1; return 0; } int main() { var1 = 2; printf("%d\n", sub()); var1 = 3; printf("%d\n", sub()); return 0; }
//sub.c int var1; // Error int sub() { int a = 1; int c = a + var1; return c; }
しかし、以下のように「言が重複している」とErrorになります。
sub.c:1:16: note: 'int var1' previously declared here int var1;
では、2つめの宣言を削除すると「宣言されていない」というErrorになります。
sub.c:6:15: error: 'var1' was not declared in this scope int c = a + var1;
この解決方法は、sub.c
での変数定義にextern
を付加します。
これで、この変数は「他の場所で定義されている変数である」と宣言することになります。
//sub.c extern int var1;
ここで、逆にmain.c
のほうにextern
を付加してもErrorになります。
undefined reference to `WinMain' collect2.exe: error: ld returned 1 exit status
これは、(おそらく)C言語では一般にmain.c
からコンパイルされるため、その変数が最初に出てくるときにextern
を付加して、「他の場所で定義されている変数である」と宣言すると「宣言されてない」というErrorになっているため、と考えられます。
例3
3つ以上のファイルで変数を共有する場合も、初出の時以外にextern
を付ければよいようです。
//main.c #include <stdio.h> #include "sub.c" #include "sub2.c" int var1; int func() { var1 += 1; return 0; } int main() { var1 = 2; printf("%d\n", sub()); var1 = 3; printf("%d\n", sub2()); return 0; }
//sub.c extern int var1; int sub() { int a = 2; int c = a + var1; return c; }
//sub2.c extern int var1; int sub2() { int a = 4; int c = a + var1; return c; }
ちなみに、sub()
とsub2()
のなかでint a = x
のように同じ名前の変数を定義していますが、これはそれぞれの関数の中でしか有効でないローカル変数であるためextern
を付加しなくてもErrorになりません。
まとめ
C言語をでのグローバル変数の定義・宣言の仕方をまとめました。
一般に「グローバル変数はどこから参照されるているか?が分かりにくくなり、意図しない場所から変数が書き換えられるのでなるべく使わないほうがいい」といわれます。
Web上にもそのような記事はたくさん出ています。
一方、実務でもよく使われています。
これは、上記のようなリスクがあっても使い勝手がいい部分があったり、どうしてもグローバル変数として使わないと逆にスパゲッティコードになってしまう、といったことがあるからだと思います。
どこから書き換えられるかわからない、という点では大規模なコードであればある程度避けられないことのように思います。
グローバル変数を使わなくても、不揮発性メモリから読み書きしたりもあります。
そういった面でもグローバル変数を使わなければいい、というものでは無いのではないか?と思います。
そのために、VS code等でもプロジェクトファイルのグローバル検索が可能ですし、Bugにならないように何重にもDebugを行ってソフトウェアの品質を確保するようになっています。