記憶クラス

スポンサーリンク

静的変数/自動変数

処理がスコープを抜ける度に破棄される変数を,自動変数 (auto variable) と呼びます。
関数内で宣言した変数は,デフォルトで自動変数となります。
宣言時に auto 指定子を付け,自動変数であることを明示することもできます。

一方,寿命の存在しない変数は静的変数 (static variable) と呼ばれます。
大域変数と,static 指定子の付いた局所変数が,静的変数になります。

次のプログラムは,自動変数と静的変数の寿命を比較する例です。

#include <stdio.h>

void f(void)
{
    auto int a = 0;    /* 自動変数 */
    static int s = 0;  /* 静的変数 */

    printf("a = %d, s = %d\n", a++, s++);
}

int main(void)
{
    f();   /* 出力: a = 0, s = 0 */
    f();   /* 出力: a = 0, s = 1 */
    f();   /* 出力: a = 0, s = 2 */
    return 0;
}

extern 宣言

他の翻訳単位で定義されている変数を参照するには,extern 宣言を用います。

次のプログラムは,複数の翻訳単位から成るプログラムの例です。

/* piyo.c */

int x = 123;
/* hoge.c */

#include <stdio.h>

int main(void)
{
    extern int x;       /* 他翻訳単位の x を参照 */
    printf("%d\n", x);  /* 出力: 123 */
    return 0;
}

このプログラムをコンパイルするには,GCC であれば次のようにします。

% gcc -o hoge hoge.c piyo.c

静的大域変数/静的関数

関数や大域変数に static 指定子を付けた場合,その関数や変数は他の翻訳単位に対して不可視化されます。

次のプログラムは,複数の翻訳単位から成るプログラムの例です。

/* piyo.c */

int x = 1;         /* 外部リンケージ */
static int y = 2;  /* 内部リンケージ */
/* hoge.c */

int main(void)
{
    extern int x, y;
    printf("%d\n", x);  /* 出力: 123 */
    printf("%d\n", y);  /* コンパイルエラー */
    return 0;
}

大域変数や関数のうち,同一翻訳単位でのみ有効なものは,内部リンケージ (internal linkage) を持つといいます。
一方,複数の翻訳単位で有効なものは,外部リンケージ (external linkage) を持つといいます。
今回の例では,piyo.c の変数 x は外部リンケージを持ち,変数 y は内部リンケージを持ちます。

レジスタ変数

頻繁に使用される変数に register 指定子を付けることで,その変数の値をレジスタに格納し,プログラムを高速化することができます。
ただし,レジスタの数には限りがあるため,register 指定子を付けたすべての変数がレジスタに格納される保証はありません。

#include <stdio.h>

int main(void)
{
    register int i;   /* レジスタ変数 */
    for (i = 0; i < 1000; i++)
        /* ... */
    return 0;
}
スポンサーリンク