6

C99でのストレージクラス指定子の正確な動作を理解しようとしていますが、仕様を誤解しない限り、一部のGCCの動作は仕様に準拠していないようです。6.2.2(2)から:

1つの変換ユニット内で、内部リンケージを持つ識別子の各宣言は、同じオブジェクトまたは関数を示します。

ただし、次のプログラムを使用してGCC(powerpc-apple-darwin9-gcc-4.2.1)をテストしました。

#include <stdio.h>
static int f() {
    static int x = 0;
    return x++;
}
static int g() {
    static int x = 0;
    return x++;
}
int main(int argc, char *argv[]) {
    printf("g() = %i\n", g());
    printf("g() = %i\n", g());
    printf("f() = %i\n", f());
    printf("f() = %i\n", f());
    return 0;
}

でコンパイルされ-std=c99、次のように出力されます。

g() = 0
g() = 1
f() = 0
f() = 1

仕様を正しく理解していれば、次のように出力されます。

g() = 0
g() = 1
f() = 2
f() = 3

GCCがここの仕様から逸脱する理由を理解しています。この動作について、より深い説明があるかどうか疑問に思っています。

4

2 に答える 2

10

6.2.2(6)では、次のように述べています。

次の識別子にはリンクがありません。[...]ストレージクラス指定子externなしで宣言されたオブジェクトのブロックスコープ識別子。

静的変数はオブジェクトのブロックスコープ識別子であり、宣言されていませんextern。したがって、それらにはリンケージがなく、特に内部リンケージはありません。

于 2010-01-29T03:16:41.733 に答える
9

次の段落6.2.2/3は重要です。

オブジェクトまたは関数のファイルスコープ識別子の宣言にストレージクラス指定子staticが含まれている場合、識別子には内部リンクがあります。

(強調されたファイルスコープ識別子に注意してください)。

静的変数xにはファイルスコープがなく、ブロックスコープがあります。

于 2010-01-29T03:08:05.960 に答える