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 セクションに保存される。だから関数を出ても値が保持されるわけです。