Связь в C: GCC следует спецификации C99, или я не понимаю спецификации? - PullRequest
6 голосов
/ 29 января 2010

Я пытаюсь понять точное поведение спецификаторов классов хранения в C99, и, похоже, что некоторое поведение GCC не соответствует спецификации, если я не понимаю спецификацию. От 6.2.2 (2):

В пределах одной единицы перевода каждое объявление идентификатора с внутренней связью обозначает один и тот же объект или функцию.

Однако я протестировал 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 будет отклоняться от спецификации здесь, мне просто интересно, есть ли более глубокое объяснение этого поведения.

Ответы [ 2 ]

10 голосов
/ 29 января 2010

В 6.2.2 (6) говорится:

Следующие идентификаторы не имеют связи: [...] область видимости блока идентификатор объекта, объявленного без спецификатора класса хранения extern.

Статические переменные являются идентификаторами области видимости объектов, и они не объявляются extern. Поэтому они не имеют никакой связи, особенно внутренней связи.

9 голосов
/ 29 января 2010

Важным является следующий параграф 6.2.2 / 3:

Если объявление идентификатора области файла для объекта или функции содержит статический спецификатор класса хранения, идентификатор имеет внутреннюю связь.

(обратите внимание на выделенный идентификатор области файла ).

Ваши статические переменные x не имеют области видимости файла, они имеют область видимости блока.

...