C 具有外部和静态变量链接的奇怪行为

C 具有外部和静态变量链接的奇怪行为,c,static,linker,external,symbols,C,Static,Linker,External,Symbols,我发现extern和static(内部)变量的一些行为非常奇怪 以下是一个例子: /* file a.c */ #include <stdio.h> /* variable with static linkage */ static int x = 24; int f() { /* variable with extern linkage */ extern int x; return x; } int main() {

我发现
extern
static
(内部)变量的一些行为非常奇怪

以下是一个例子:

/* file a.c */
#include <stdio.h>

/* variable with static linkage */
static int x = 24;

int f() {
        /* variable with extern linkage */
        extern int x; 
        return x;
}

int main() {
        printf("%d\n", f());
        return 0;
}
我使用以下方法编译此程序:

$ cc a.c x.c -o a
然后我运行我的程序并获得以下输出:

$ ./a
24
为什么这个程序输出
24
而不是
100

引用

下表标识了分配给在单个转换单元中声明两次的对象的链接。列指定第一个声明,行指定重新声明

同样来自标准第6.2.2节:

对于使用存储类说明符extern声明的标识符,在该标识符的先前声明可见的作用域中,如果先前声明指定了内部或外部链接,则该标识符在以后声明中的链接与在先前声明中指定的链接相同。如果之前的声明不可见,或者之前的声明未指定任何链接,则标识符具有外部链接

因此,文件
a.c
的所有外部链接都在内部解决。
您的代码首先将
x
定义为静态,然后在翻译单位a.c.中定义为外部。因此,上表中的链接是内部链接。所以它打印
24

“静态”不是链接。链接有“外部”、“内部”和“无”。可能的重复可能与链接器的工作方式有关。链接器将始终在当前编译单元中搜索给定标识符的定义,然后再在其他单元中搜索。例如,你也可以在你的代码中重新定义一些
C
库函数,并使用它们来代替标准函数。不要说这个问题完全是那个问题的翻版,但其中的一个答案详尽无遗地进入了标准,我相信它解释了你观察到的行为。局部作用域屏蔽了全局作用域。该表虽然精神上很好,但混淆了说明符和链接<代码>外部和
静态
是说明符,但“无链接”是链接。命名空间作用域中的声明不需要任何说明符,但会导致外部或内部链接,但不是无链接。该链接(和表)是错误的——请阅读您引用的标准部分!如果该标识符的先前声明是可见的,则实际上会忽略
extern
,链接类型由先前的可见声明确定。表的最后一列不是也说明了与我引用的标准相同的事情吗?我错过什么了吗?
$ ./a
24