Я пытаюсь понять точное поведение спецификаторов класса памяти в 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 отклонился бы от спецификации здесь, я просто задаюсь вопросом, существует ли более глубокое объяснение этого поведения.
Следующий параграф, 6.2.2/3, важен:
Если в объявлении идентификатора области видимости файла для объекта или функции содержится статический спецификатор класса хранилища, то идентификатор имеет внутреннюю связь.
(обратите внимание на подчеркнутый идентификатор области действия файла ).
Ваши статические переменные x
не имеют области видимости файла, они имеют область видимости блока.
В пункте 6.2.2 (6) сказано:
Следующие идентификаторы не имеют связи: [...] область действия блока идентификатор объекта, объявленного без экстерна спецификатора класса хранилища.
Статические переменные являются блочными идентификаторами области видимости для объектов, и они не объявляются extern
. Поэтому они не имеют никакой связи, особенно внутренней.