2010-01-29 51 views
6

我想了解C99中的存储类说明符的确切行为,有些GCC行为似乎不遵循规范,除非我误解了规范。从6.2.2(2):C中的链接:GCC是否遵循C99规范,或者我不理解规范?

内的一个翻译单元,标识符的每个声明与内部联动表示相同对象或功能。

然而,我与以下程序测试GCC(PowerPC的苹果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 

我明白为什么海湾合作委员会会偏离这里的规范,我只是想知道这个行为是否有更深的解释。

回答

9

下一段,6.2.2/3,是很重要的:

如果对象或功能的文件范围标识符的声明包含存储类说明静态的,标识符具有内部联系。

(注意强调的文件范围标识符)。

你的静态变量x没有文件范围,它们有块范围。

+0

换句话说,每个x都是声明它的函数的局部。 – 2010-01-29 03:11:30

+0

谢谢。很容易遗漏规范中的单词。 – 2010-01-29 03:19:55

+2

@Dietrich:是的。事实上,这很容易,我错过了更相关和重要的部分,作为答案张贴。 – 2010-01-29 04:06:50

10

在6.2.2(6),它说:

以下标识符没有起重:[...]块范围中声明 标识符的对象,而不存储类说明的extern 。

静态变量是对象的块范围标识符,它们未声明为extern。因此他们没有联系,特别是没有内部联系。

+2

+1;这比我引用的段落更有意义。 – 2010-01-29 03:19:08