我正在尝试理解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会偏离这里的规范,我只是想知道这种行为是否有更深层次的解释。
答案 0 :(得分:10)
在6.2.2(6)中它说:
以下标识符没有链接: [...] 块范围 没有存储类说明符extern声明的对象的标识符。
静态变量是对象的块作用域标识符,并且它们未声明为extern
。因此它们没有联系,特别是没有内部联系。
答案 1 :(得分:9)
下一段6.2.2 / 3非常重要:
如果对象或函数的文件范围标识符的声明包含静态的存储类说明符,则标识符具有内部链接。
(请注意强调的文件范围标识符)。
您的静态变量x
没有文件范围,它们具有块范围。