【问题标题】:Why won't extern link to a static variable?为什么外部链接不指向静态变量?
【发布时间】:2011-02-19 23:16:34
【问题描述】:

为什么extern int n 在声明 n 时(在不同的文件中)static int n 不编译,但在声明 int n 时工作? (这两个声明都在文件范围内。)

基本上,为什么文件范围内的int n 与同一范围内的static int n 不一样?它仅与外部有关吗?如果是这样,我错过了 extern 呢?

【问题讨论】:

    标签: c static extern


    【解决方案1】:

    static 的全部目的是声明一个变量对声明它的源文件是私有的。因此,它在防止来自外部的连接方面恰恰是在做它的工作。

    请记住,文件范围变量定义有四种风格:

    1. int blah = 0; — blah 在此文件中定义并可从其他文件访问。其他文件中的定义重复,会导致错误。
    2. extern int blah; — blah 必须在别处定义并从此文件中引用。
    3. int blah; — 这是 FORTRAN COMMON 的道德等价物。您可以在文件中包含任意数量的这些,并且它们都由链接器解析为一个共享的int。 (*)
    4. static int blah;(可选带有初始化程序)——这是静态的。它对该文件是完全私有的。它对其他文件中的外部人员不可见,并且您可以有许多不同的文件都声明static TYPE blah;,并且它们都是不同的

    对于听众中的纯粹主义者:'file' = 编译单元

    请注意,静态内部函数(不在文件范围内)的范围更加紧密:如果两个函数即使在同一个文件中声明 static int bleh = 0;,它们也是不相关的。

    (*):对于那些不熟悉的人:在通常的模式中,一个编译单元必须定义一个全局变量,其他编译单元可以引用它。它“生活”在那个编译单元中。在上述情况 (3) 中,没有文件(或所有文件)定义它。如果两个文件说int blah = 0;,链接器将抱怨多个定义。如果两个文件说int blah;,链接器会愉快地创建一个全局int,并导致所有代码引用它。

    【讨论】:

    • 那么 'int n' 会被调用(在文件范围内),就存储说明符而言?
    • @bmargulies:你的意思是在文件范围内?因为在函数范围内,静态 var 是在函数返回后保留其值的变量,而在类范围内,静态成员具有可用于所有对象的单个实例。
    • @Jared——我称之为“普通”。在我的回忆中,该语言没有定义一个关键字来明确这一点。如果我错了,我相信有人会纠正我。
    • @bmargulies:好的,我想用 C++ 术语而不是 C。谢谢。
    • 呵呵。您通过指出一个类似的 fortran 构造来“澄清”。我认为没有多少 SO 用户对 Fortran 感到困惑。 :)
    【解决方案2】:

    在标准 C 中,在函数外部声明的变量有两个作用域。 static 变量仅在声明它的编译单元(即文件)内可见,非静态变量在整个程序中可见。 extern 声明表示变量的位置尚不清楚,但将由链接器进行排序;它与非静态变量兼容,但 extern static 简直是疯话!

    当然,在实践中,这些天还有其他可见性。特别是,现在在单个源文件和整个程序之间存在范围级别;单个共享库的级别是有用的(可通过 GCC 函数属性等机制设置)。但这只是非静态变量主题的一种变体; static 保持与之前相同的解释。

    【讨论】:

      【解决方案3】:

      根据 MSDN 文档:

      修改变量时,static关键字指定变量具有静态持续时间(程序开始时分配,程序结束时解除分配)并将其初始化为0,除非指定另一个值。 在文件范围内修改变量或函数时,static 关键字指定变量或函数具有内部链接(其名称在声明它的文件之外不可见)。

      Static (C++) on MSDN:2015年1月存档;另请参阅最新文档:static § Storage classes (C++) | Microsoft Docs

      【讨论】:

        【解决方案4】:

        iv.c:2:1: 错误:声明说明符中有多个存储类 外部静态int i; ^

        这就是我们尝试外部静态变量的结果。声明 extern static int i; - 类似于声明 float int i; 你不能让 float 和 int 出现在同一个声明中,对吧?同样,您不能在同一个声明中包含 extern 和 static。

        【讨论】:

          猜你喜欢
          • 2016-05-16
          • 1970-01-01
          • 1970-01-01
          • 2013-06-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多