【问题标题】:Weird behavior with extern and static linkage of variables变量的外部和静态链接的奇怪行为
【发布时间】:2016-05-16 19:13:10
【问题描述】:

我发现externstatic(内部)变量的一些行为我觉得很奇怪。

这是一个例子:

/* 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;
}

-

/* file x.c */
/* define symbol `x` to be an `int` equal to 100 */
int x = 100;

我编译这个程序使用:

$ cc a.c x.c -o a

然后我运行我的程序并得到这个输出:

$ ./a
24

为什么这个程序输出的是24而不是100

【问题讨论】:

  • "static" 不是链接。链接是“外部”、“内部”和“无”。
  • 这可能与链接器的工作方式有关。链接器总是先在当前编译单元中搜索给定标识符的定义,然后再在其他编译单元中搜索。例如,您还可以在代码中重新定义一些 C 库函数并使用它们来代替标准函数。
  • 并不是说这个问题完全是对那个问题的欺骗,但是其中的一个答案在标准中详尽无遗,我相信它可以解释您在此过程中观察到的行为。
  • 一句话概括。本地范围掩盖全局范围。

标签: c static linker external symbols


【解决方案1】:

引用link

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

同样来自标准的 6.2.2 节:

对于使用存储类说明符 extern 声明的标识符,在该标识符的先前声明可见的范围内,如果先前声明指定内部或外部链接,则后面声明的标识符的链接是相同的作为先前声明中指定的链接。如果前面的声明不可见,或者前面的声明没有指定链接,则标识符具有外部链接。

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

【讨论】:

  • 该表虽然在精神上很好,但混淆了说明符和链接。 externstatic 是说明符,但“无链接”是链接。命名空间范围内的声明不需要任何说明符,但会导致外部或内部链接,但不是没有。
  • 那个链接(和表格)是错误的——阅读你引用的标准部分!如果该标识符的先前声明可见extern 将被有效忽略,并且链接类型由该先前可见声明确定。
  • 表格的最后一列不是和我引用的标准一样吗?我错过了什么吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-08-06
  • 1970-01-01
  • 2023-03-18
  • 2012-07-01
  • 1970-01-01
  • 2011-02-19
相关资源
最近更新 更多