【问题标题】:Whether Global Variables in C, static or extern?无论是 C 中的全局变量、静态变量还是外部变量?
【发布时间】:2020-08-17 08:18:55
【问题描述】:

我刚开始学习 C 编程。 在一些书籍和网络文章中,我可以发现 C 中的任何全局变量默认对应于static 存储类,但具有外部链接。 这是否意味着它部分是static,部分是extern?因为据我了解,任何带有static 存储类说明符的全局变量都只有内部链接,并且可以在同一个文件中访问。

P.S:我提到了这个问题 Global variables in C are static or not? ,但无法真正了解全局变量在 C 中默认是 static 还是 extern

【问题讨论】:

  • 该标准还在C11 Standard - 6.2.4 Storage durations of objects 中提供了有关对象的存储持续时间 的详细信息。确保您了解extern 存储类与变量是否对其他源可见有关,而存储持续时间 与每个存储类中定义的生命周期有关。
  • “我提到了这个问题 Global variables in C is static or not? ,但无法真正了解全局变量在 C 中默认是静态还是外部” - 链接答案的第一行说:如果不指定存储类(即extern或static关键字),则默认全局变量有外部链接。.
  • @P.P 你的意思是全局变量的默认存储类是 extern 吗??
  • 伙计们,请停止使用extern 作为形容词。由于这个问题是关于 C 标准中一些混乱的术语,我们应该清楚。 staticextern 是关键字;它们是源代码中的文本。 “静态”和“外部”是形容词;它们出现在具有多种含义的短语中。 “外部链接”是指一个名称可以引用(链接到)多个翻译单元中的同一对象。 “外部声明”是指任何函数之外(外部)的声明。如果上下文不清楚,单独说“外部”可能会产生歧义。
  • 此外,关键字staticextern 都具有多种效果,并且根据它们出现的位置而具有不同的效果,因此说某些标识符是externstatic 并不清楚具体特征有意的。

标签: c static linkage storage-class-specifier


【解决方案1】:

C 中的全局变量默认对应static 存储类,但具有外部链接。这是否意味着它部分是static 部分是extern

英文单词“static”在 C 中具有混淆和多重含义,是的,在函数外部声明的变量的默认值是具有静态存储持续时间和外部链接。

由于这里有多个概念和一些混合使用的词义,我们应该澄清一些术语和格式:

  • 使用代码风格来引用源代码中的特定文本,例如关键字static。在谈到静态存储时长或外部链接时,“静态”和“外部”只是英文形容词,不应采用代码风格。
  • “全局”表示在整个程序中可见。 C 标准没有为此目的使用这个词。它使用“外部”来指代任何功能之外(外部)的事物。 (但它也将“外部”用于其他目的。)全局变量不能有内部链接,因为它不会在整个程序中可见。
  • 变量由一个对象(为表示值而保留的内存)和一个标识符(名称)组成。存储持续时间是对象的一个​​属性。链接是标识符的一个属性。

英文单词“static”一般表示不变。 C 标准以多种方式使用这个词和关键字static

  • 静态存储持续时间意味着对象的内存在整个程序执行过程中都会保留。
  • 在声明中使用 static 关键字,除了下面的之外,都给出了对象静态存储持续时间,并且在函数外部的声明中,给出了标识符内部链接。
  • 在参数声明的下标标记中使用static 关键字,如@9​​87654328@,表明参数至少指向规定数量的元素。
  • 使用_Static_assert 的静态断言提供编译时测试(这可以帮助检测错误或确保正在使用预期设置编译程序)。

不幸的是,这些多重用途至少部分是由于 C 语言的开发历史。

【讨论】:

    【解决方案2】:

    当您不打算使用在不同文件的一个文件中声明的variable 时,您应该在声明之前使用static 关键字

    file1.c:

    static int number = 63;   // this variable is used only in this file
    
    ...
    

    file2.c:

    float brightness = 0.5;   // is needed in some Other file;
    
    ...
    

    file3.c:

    extern float brightness;  // use external declaration to use it here
    
    ...
    

    尽可能使用静态变量。

    如果您想在两个不同的translation units(c 文件)中使用两个global 变量,那么您的编译器将抛出一个错误,指出该变量已在别处声明。

    使用static 将使其对其他翻译单元隐藏。

    【讨论】:

    • 我的错,我会改的
    • @DhruvVanjari 明白了!!但我怀疑“使用静态是否会使其对其他翻译单元隐藏。”然后全局变量的默认存储类不能是静态的。如果我错了,请纠正我。
    【解决方案3】:

    你混淆了static静态存储持续时间

    存储期限和链接是不同的术语。 C 中没有任何东西称为“全局”,尽管该术语经常被随意地用于在 文件范围 声明的任何变量 - 即:在任何函数之外。更正确地使用术语“全局”是变量具有外部链接,这意味着它可以在整个项目中的任何位置引用。

    在文件范围内声明的所有变量都有静态存储持续时间。这决定了这些变量是如何初始化的,并且它们在程序的整个执行过程中持续存在(实际上,这也可能意味着变量最终出现在实现的.data.bss 段中)。

    在文件范围内声明但没有任何存储类说明符的变量(staticextern 都没有)具有外部链接,但它仍然具有静态存储持续时间.从 6.2.4 开始:

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

    但是,如果您将存储类说明符添加到文件范围变量中,则您同时指定存储持续时间和链接。 6.2.4/3:

    如果对象或函数的文件范围标识符的声明包含存储类说明符static,则该标识符具有内部链接。

    正如你所说,具有内部链接的变量只能从同一个文件中引用(严格来说是相同的“翻译单元”)。

    如果您将static 添加到局部变量,这里会有一些细微的差别——然后它指定存储持续时间而不是链接。整个术语链接是相当混乱的 - 简单地说,该术语的目的是规定两个具有相同名称的变量何时引用相同的对象或不同的对象。对于那些制作编译器/链接器的人以及意大利面条程序员来说,这主要是一个问题。遵循以下建议,避免属于后者。


    初学者不必担心以上任何问题。 初学者的经验法则:

    • 切勿在函数外部声明变量,除非它们是 static
    • 切勿在头文件中声明变量。
    • 永远不要使用extern
    • 如果函数不打算从其他文件调用,请在函数前面使用 static

    这将使您走得更远,您实际上需要在不同文件之间共享变量的极少数情况是另一个故事/高级主题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-05-13
      • 1970-01-01
      • 2015-06-12
      • 1970-01-01
      • 2017-12-30
      • 1970-01-01
      • 2012-06-13
      相关资源
      最近更新 更多