法大奥山研究室

 previous  contents

16.4. オブジェクトの寿命:静的記憶域期間と自動記憶域期間


 変数が値を記憶するためのメモリ領域を確保している期間をその変数の「寿命」(lifetime)と言います。変数の寿命は,プログラム内でメモリの割り当て(allocate)をしない限り,次の2つとなります。[C99, 6.2.4]

■記憶域期間(Storage Duration)

今後は,自動記憶域期間をもつ変数を「自動変数」,静的記憶域期間をもつ変数を「静的変数」と略称することとします。

 初期化は,記憶域期間によってルールが異なります。

/* Example 16.4 */

#include <stdio.h>

int n;
static double r = 3.14;

int main(void)
{
       printf("n = %d\n", n);
       printf("r = %f\n", r);
 
       {
              extern double r;
              int n = 2;
              static long l = 1234567890L;

              printf("n = %d\n", n);
              printf("r = %f\n", r);
              printf("l = %ld\n", l);
       }

       printf("n = %d\n", n);
       printf("r = %f\n", r);
       printf("l = %ld\n", l); /* コンパイル・エラー */

       return 0;
}

最初の変数 n外部結合をもつので静的変数です。上の場合 0 に初期化されます。変数 r内部結合をもつので静的変数となり,3.14 と初期化されます。次に main関数の中にあるブロック { } 内ですが,

extern double r;

の変数 r は,6行目で宣言した内部結合をもつ静的変数 r同じリンケージ(内部結合)を持つこととなります。したがって,ブロック・スコープを持ちながらリンケージも持つので初期化はできません。初期化は,その外部定義(6行目)に従います。一方,

int n = 2;

は,5行目で 0 と初期化された外部結合をもつ変数 n隠す(hide)ため,これとは別個のプロック・スコープをもつ int型自動変数 n を定義することとなり,2 と初期化されます。また,

static long l = 1234567890L;

は,long型変数 l1234567890 と初期化しています。この変数は,リンケージは持ちません。しかし,static を付しているので静的変数です。静的変数ですがブロック・スコープを持つので,その有効範囲外では使用できません。ソース内の

printf("l = %ld\n", l); /* コンパイル・エラー */

部分を削除せずにコンパイルすると,`l' undeclared といった具合に「宣言されていません」というエラーが出ます。エラーが出ないように修正したものをコンパイルし,実行ファイルを実行すると,次の出力を得ます。

n = 0
r = 3.140000
n = 2
r = 3.140000
l = 1234567890
n = 0
r = 3.140000

上の変数 l のようなプロック・スコープをもつ静的変数をその有効範囲外で参照するにはどうすれば良いのか,あるいは,そもそもそのような変数をいつ使用するのか,といった疑問を持ったことでしょう。次はその例です。

/* Example 16.5 */

#include <stdio.h>

char *f (void);

int main (void)
{
       char *y;
       y = f();
       printf("%s [%p]\n", y, y);
       return 0;
}

char *f (void)
{
       static char str[8] = "testing";
       char *x = str;
       return x;
}

これは malloc でメモリを割り当てる Example 10.17static を使って静的に割り当てたケースです。ポインタを渡せば,有効範囲外でも参照することができます。

仕様書(C99)理解度 ○×クイズ
1. static を付せば,結合をもつ。
2. static を付せば,内部結合をもつ。
3. extern を付せば,結合をもつ。
4. extern を付せば,外部結合をもつ。
5. 変数の寿命を静的記憶域期間にするには,static を付さなければならない。
6. 外部宣言された変数の寿命は,静的記憶域期間となる。

答え:1 × 2 × 3 ○ 4 × 5 × 6 ○

* C99 を作成していた人達によると,スコープリンケージ記憶域期間は,伝統的に混乱していた領域であったという。(ISO/IEC JTC1/SC22/WG14, A draft rationale for the C99 standard (N897), p.30.)


 previous  contents