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