2011-01-21 12 views
2

Cでは、静的変数はどこに格納されていますか? 2つの静的変数があるとします.1つは関数に対してローカルであり、もう1つはグローバルです。このエントリはシンボルテーブルでどのように管理されていますか?説明してください。静的変数記憶

+2

Cにはシンボルテーブルがありますか? – leppie

+0

"静的変数"とはどういう意味ですか?静的記憶期間?または内部リンケージ? – AnT

答えて

13

では、インプリメンテーションが適切とみなされる場所に格納できます。 Cの標準は、実装がどのようにして動作するかを指示するものではなく、の動作のみを指示します。

通常、すべての静的記憶期間変数(関数内の静的変数および関数外のすべての変数)は、ファイルレベルでの関数であるか関数内であるかにかかわらず、同じ領域に格納されます。

上記のかっこ内のビットが重要です。関数の外では、staticは関数内でのように変数の格納期間を決定しません。変数が現在の翻訳単位の外側に表示されているかどうかを判断します。 すべて関数外の変数は、静的な記憶期間です。

シンボルテーブルに関しては、ビルドプロセス中にのみ存在するコンストラクトです。実行ファイルが生成されると、シンボルはありません(デバッグ情報はもちろん除外されますが、コードの実行とは関係ありません)。その時点での変数への参照はすべて、ハードコーディングされたアドレスまたはオフセットになります。

つまり、どの変数を参照しているのかを名前で調べるのはコンパイラです。


ここでは、変数の格納方法の例を参照できます。以下の小さなCプログラムを考えてみましょう:

#include <stdio.h> 
int var1; 
static int var2; 
int main (void) { 
    int var3; 
    static int var4; 

    var1 = 111; 
    var2 = 222; 
    var3 = 333; 
    var4 = 444; 

    return 0; 
} 

これは、次のアセンブリを生成:

.file    "qq.c" 
.comm    var1,4,4 
.local   var2 
.comm    var2,4,4 
.text 
.globl   main 
.type    main, @function 
main: 
    pushl   %ebp 
    movl   %esp, %ebp 
    subl   $16, %esp 
    movl   $111, var1 
    movl   $222, var2 
    movl   $333, -4(%ebp) 
    movl   $444, var4.1705 
    movl   $0, %eax 
    leave 
    ret 
.size    main, .-main 
.local   var4.1705 
.comm    var4.1705,4,4 
.ident   "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3" 
.section   .note.GNU-stack,"",@progbits 

をそして、あなたはvar1var2var4(静的記憶域期間のもの)はすべてに.commラインを持っていることがわかりますそれらをリンカによる統合の対象となる共通エントリとしてマークします。リンカーは、他のオブジェクト・ファイルに未解決の外部を満たすためにそれらを使用しないように

また

var2var3及びvar4(現在transdlation部外見えないもの)はすべて、.localラインを有しています。

そして、ファイルをリンクしながら、ld --verboseの出力を調べることによって、あなたはすべての一般的なエントリは.bssエリアに終わることがわかります。

static int a_static_var = 5; 

void foo(void) 
{ 
    static int a_static_var = 6; 

    return; 
} 

:以下のソースを考えると

.bss   : 
    { 
    *(.dynbss) 
    *(.bss .bss.* .gnu.linkonce.b.*) 
    *(COMMON) 
    : : : 
    } 
+0

Cコードからasmコードを生成するために使用したツール。 –

+1

@prp、 'gcc -S'はアセンブリコードを標準出力に出力します。 – paxdiablo

+0

本当にthnx男..あなたはコンパイラでオタクのように思える.. –

1

すべてのコンパイラに一般化することは不可能ですが、これは最も頻繁に行われます。

ロード時に初期化されますが、実行時に変更可能な変数のリンカーによって、メモリブロックが確保されます。すべての静的変数は、ローカルかグローバルかに関係なく、このブロックに配置されます。

0

Visual Studioは以下のように変数をコンパイルします(この例では、詳細はコンパイラごとに異なり、オプションによって異なります)。

_DATA SEGMENT 
_a_static_var DD 05H 
[email protected][email protected]@[email protected] DD 06H   ; `foo'::`2'::a_static_var 
_DATA ENDS 

したがって、両方の静的変数はデータセグメントになります。関数にスコープされた静的変数は、別の関数またはソースファイルと同様の変数と「一致」しないように名前が変更されています。

コンパイラの実装ではこれは自由に処理できますが、一般的な考え方は通常似ています。