【问题标题】:Scope of a variable outside main in CC中main之外的变量范围
【发布时间】:2011-07-03 20:41:28
【问题描述】:

考虑代码:

#include <stdio.h>

int x;

int main (void) 
{ }

x 的值是0main 中。但这是为什么呢?我还没有声明它是static。还是假设 static 在函数之外?

如果上述情况属实,它与extern 有何不同?

【问题讨论】:

  • 你能澄清你关于extern的问题吗?
  • 如果我要声明一个外部变量,是不是也一样?
  • this 和 extern 的区别在于 extern 是外部的,而 this 不是。
  • 这个主题经常被误解,在 SO 上似乎没有很好的问题和很好的答案。
  • 您可能会发现 thisthisthis 很有用。

标签: c variables


【解决方案1】:

既不是static,也不是extern。它是一个对其所在的编译单元可见的变量,并且在所有声明 xextern 变量的编译单元中也可见。

为什么我说既不是static也不是extern

如果是extern,那么,一定有一个不同的编译单元,上面有x声明。显然这是您唯一的编译单元。

如果是static,则不允许extern 引用此编译单元中定义的x 变量。我们知道我们可以很容易地为这里声明的x 声明一个extern 变量。

为什么将0 分配给x?因为,在 C 中,所有全局变量都初始化为 0。在 C99 标准的 6.7.8 (10) 中是这样说的。

【讨论】:

  • 啊,我明白了。那么为什么要初始化为 0 呢?
  • @Kanishk:考虑一个包装你工作的 file 的函数。这是此声明的范围。 extern 的作用域跨越多个文件。
【解决方案2】:

当我们说“静态存储时长”的变量被隐式初始化为0时,我们并不是说需要在它们前面加上“静态”关键字。

“静态存储持续时间”只是对象的一种特定类型的存储持续时间,表示它们的存储持续整个程序的持续时间。这种存储持续时间用于在文件范围内声明的变量(如您的变量)和局部静态变量。

【讨论】:

    【解决方案3】:

    6.2.2/5:“如果对象标识符的声明具有文件范围且没有存储类说明符,则其链接是外部的。”

    这是链接,但不是范围。无论哪种方式,您对x 的声明都将具有文件范围。 staticextern 不会影响范围。它被初始化为 0,因为 x 具有静态存储持续时间(参见 6.2.4/3 和 /5)。

    一般来说你还必须了解 6.2.2./4:

    对于用 存储类说明符 extern 在 事先声明的范围 该标识符是可见的,如果 事先声明指定内部或 外部联动,联动 后面声明的标识符是 与指定的链接相同 事先声明。

    因此,使用extern 声明与不使用存储类说明符声明并不完全相同。不过,在您的示例中,没有事先声明。

    【讨论】:

    • 标准是圣杯,在我之前问的另一个问题中,人们引用了标准。不过谢谢:-)
    • @Kanishk:引用标准是一个持续的过程,你引用它的次数越多,它的风格和术语就越有意义。然后,您就可以摆脱依赖教程中的示例、记住一半的规则和直觉:-)
    【解决方案4】:

    它不是静态的。它是全球性的。您可以在不同的编译单元中声明它extern,但会在这个编译单元中为其分配空间。顺便说一下,如果没有给定初始化器,全局变量总是被初始化为 0。

    【讨论】:

    • 所以当我使用关键字extern 将它称为另一个编译单元时,它使它成为一个外部变量,但对于这个文件,它是全局的。对吗?
    • @Kanishk:它在两个文件中都是全局的,只是另一个文件中的extern 声明不会导致分配任何空间。它从链接器获取地址,链接器从这个文件中获取地址。
    【解决方案5】:

    您的编译器将 x 的值初始化为 0。

    这是一个全局变量,在main() 中可见

    【讨论】:

    • 但是当我希望它是一个外部变量时,我也会这样做。那么有什么区别呢?
    • 我没有听懂你的问题?你期待什么你没有看到?
    • Pablo 的回答解决了这部分问题。
    【解决方案6】:

    x 是一个全局变量,在程序启动时为它分配空间并初始化为 0(通常,但是你应该有一个显式的初始化器)。

    “静态”关键字有两种不同的含义。

    1)

    静态整数 x;
    
    int main() { }
    

    这将 x 的范围限制为单个文件。虽然它仍然是一个全局变量,但链接器将无法连接其他文件对 x 的引用。

    2)

    int main() {
       静态整数 x;
    }
    

    这有效地将 x 变成了一个全局变量。虽然作用域仍然在 main 函数中,但它的空间是全局分配的,它的值将在 main() 调用之间保留。

    【讨论】:

      【解决方案7】:

      这感觉像是一道作业题,但无论如何我都会咬牙切齿的。

      要在另一个文件的类或函数中使用您在此处定义的 x,您可以使用

      extern int x;
      

      在您使用 x 变量(如在标题中)之后,您可以像在 main() 中一样使用 x。 extern 告诉编译器您正在使用在别处定义/实例化的变量。

      如果您希望它在 main 运行之前存在,那么您可以使用在 main() 运行之前处理的 static。换句话说,它在启动任何处理之前(在 main 中)使用变量加载内存空间。

      至于为什么它在启动时为 0,那可能只是你的编译器给它一个基值。并非所有编译器都这样做,除非我弄错了,否则许多编译器只会给您分配给 x 的内存空间中的任何内容,这可能是任何内容。换句话说,它们为您提供了完整的内存,其中包含预先包含的任何数据(或部分数据)。

      【讨论】:

      • 这个作业怎么样?我不是要你为我写代码。我在问一些我尝试过的东西。家庭作业问题不是这样的。
      猜你喜欢
      • 2011-12-06
      • 2012-07-16
      • 1970-01-01
      • 2016-01-05
      • 2021-12-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多