UP | HOME

static/autoとは何か - 2023年度 システムプログラミング

static/auto とは何か

C言語から見た static と auto の違い

以下の1行目で宣言されている変数は,static(静的)変数, 一方,5行目で宣言されている変数は,auto(自動)変数であるという.

 1: int primes_stat[10];
 2: 
 3: main()
 4: {
 5:   int primes_auto[10];
 6: 
 7:   primes_stat[0] = 2;
 8:   primes_auto[0] = 3;
 9: 
10:   print_int(primes_auto[0];)
11:   print_int(primes_stat[0];)
12: }

C言語のstatic変数は,以下の特徴を持っている.

  • プログラムの開始から終了まで,値を保持しつづける.

一方,auto 変数は,以下の特徴を持っている.

  • 関数の中で宣言され,その関数の実行開始時から 終了時までの間,その値を保持する.

この特徴の違いは,アセンブラ内でどのような記述の違いとして 生じているのかを調べてみよう.

static 変数のアセンブラ表現

report2-1.c と,それに対応する report2-1.s から primes_stat を探すと, アセンブラで,以下の行を発見する.

.comm   _primes_stat,40

これは,

.data
.align 2
_primes_stat:
   .space 40

と同等と考えてよい.つまりデータセグメント内にデータを40バイト確保している. この領域は,primes_stat のためだけに使用されるので, プログラムの開始から終了まで, 値を保持しつづけるという性質を持つことになる. いいかえれば,primes_stat は常にその領域しか使用しないので, 関数などが再帰的に呼び出された場合は,その領域を上書きすることがある. つまり,

  • プログラムの開始から終了まで,値を保持しつづける一方で, 固定された領域(staticな領域)のみを使用するので, 再帰やスレッドによる並行処理では,上書きの危険がある.

といえる.

auto 変数のアセンブラ表現

一方,auto 変数である,primes_auto は, report2-1.c にはあるが,report2-1.s からそれらしい部分を簡単に発見することができない.

以下,抜粋:

 1: $LC4:
 2:       .ascii  "primes_auto[0]\000"
 3:       .text
 4:       .align  2
 5: 
 6: main:
 7:       subu    $sp,$sp,64
 8:       sw      $ra,60($sp)
 9:       sw      $fp,56($sp)
10:       move    $fp,$sp
11:       li      $v0,2                   # 0x2
12:       sw      $v0,_primes_stat
13:       li      $v0,3                   # 0x3
14:       sw      $v0,16($fp)
15:       la      $a0,$LC3
16:       lw      $a1,_primes_stat
17:       jal     _print_var
18:       la      $a0,$LC4
19:       lw      $a1,16($fp)
20:       jal     _print_var
21:       move    $sp,$fp
22:       lw      $ra,60($sp)
23:       lw      $fp,56($sp)
24:       addu    $sp,$sp,64
25:       j       $ra

唯一,文字列だけから抜粋の02行目にみつけることができる. これを頼りに手繰ると,18行目で $LC4 を使っていることから, 20行目で呼出している print_var の第2 引数が primes_auto[0] の値 であると分かる.つまり,19行目の $a1 ,さらに遡ると 16($fp) のことである. $fp新$sp と同じアドレスを指すので, primes_auto新$sp + 16 バイト目にあることが分かる. つまり,スタック上に存在している.(各自スタックの絵を書いてみるとよい)

primes_auto は,24行目の $sp 操作によって, この関数呼出しが終わった瞬間に領域を開放して,値が使えなくなる.

main 関数における自動変数宣言は, 「関数の終了」=「プログラムの終了」に近いため, 変数の寿命についてあまり意識することはない.

C言語における static というキーワード

C言語において static というキーワードは,2つの意味を持っているため, 誤解を生じやすい.1つは,上記で説明した,静的記憶クラスを使用するという指定である. 具体的にいうと,スタック上ではなく,プログラム中に静的に存在する領域にデータを確保するという意味である.

もう1つは, static を付けるとスコープ(変数が外部から参照できる範囲) が変化するということである. 具体的には,関数外(ファイルの先頭など)で static を付けて宣言した変数は, 外部のファイルからは参照できない. 簡単にいうと,複数の .c ファイルから構成されるプログラムにおいて, あるファイル内だけからしか参照できない変数を宣言できる.

このように static が2つの意味を持つために, static の使い方を誤解している場合がある.

static は,関数内でも有効に働くので,その場合はスコープ(変数の有効範囲) ではなく,記憶クラスを指定するのだと理解して欲しい. 以下に宣言とその解釈の一覧を示す.

宣言例 スコープ:見える範囲 記憶クラス(寿命)
static int a; (関数内) 関数内 静的(プログラム中)
static int a; (関数外) ファイル全体 静的(プログラム中)
int a; (関数内) 関数内 自動(関数中)
int a; (関数外) プログラム全体 静的(プログラム中)

Author: Yoshinari Nomura

Emacs 27.1 (Org mode 9.3)