てけもぐ Tech 忘備録

Cの static 付きローカル変数の保存場所

対象読者

C言語初学者

解決すること

static ローカル変数がどこに保存されるのかとか、なぜ値が保存されるのかとか。

内容

C言語の変数に付ける static 指定は、関数外のやつと関数内のやつがありますけども、関数内の static 変数について少し。

関数外のやつとか、関数に付ける static っはアクセスの制限を課すものですけど、関数内のやつってちょっと変わった動きじゃないでしょうか?

static 付き局所変数(ローカル変数)も関数内からしかアクセス出来ない局所変数ですけど、関数呼び出しを出ても値が保持されますよね。これに少し違和感を感じるのは私だけ?

例えば。

int g_value=100;

int foo(int i){
  static int value=10;
  return value=i;
}
int main(){
  return foo(100);
}

上のコードを gcc -S としてコンパイルしてアセンブラにした時、static 変数 value は以下の様になってます。(-masm=intel のインテル表記)

...
	.data
	.align 4
	.type	value.0, @object
	.size	value.0, 4
value.0:
	.long	10
...

んで、global 変数のg_value 方は、以下の様に。

...
	.globl	g_value
	.data
	.align 4
	.type	g_value, @object
	.size	g_value, 4
g_value:
	.long	100
...

関数定義の外、.data セクションにあるので、static を付けた局所変数も場所としては広域変数と同じということです。.globlが付いていないので他のファイルからはアクセス出来なくなっています。

でも、関数内でなくファイル全体に対する定義として書かれているとすると、他の関数内に同じ名前の static 局所変数があったら重複してしまいますよね。そこでコンパイラの方で value.0 .0が付けられてます。コンパイラによって色んな方法があるのでしょうけど、この数値が増えていくことで名前の重複を避けてます。

つまり、仕組みとしてはファイル単位での変数。関数のスタック上に置かれるわけではないので、どっちかと言うと広域変数に似てます。

普通の局所変数は、関数のスタックフレームの中に場所が用意されるので、関数を呼ぶ度に場所が確保され違う値を保持しますが、static が付くと(初期値ありの場合) .data セクションに保存される。だから関数を出ても値が保持されるわけです。

Tags