C 中的全局变量是静态的还是外部的?

Whether Global Variables in C, static or extern?

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

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

只要您不打算在另一个文件中使用在一个文件中声明的 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 将使其对其他翻译单元隐藏。

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

存储期限和链接是不同的术语。 C 中没有什么叫做“全局”的,尽管这个术语经常草率地用于在 文件范围 声明的任何变量——即:在任何函数之外。更正确地使用术语“全局”是变量具有外部链接,这意味着它可以在整个项目的任何地方引用。

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

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

If the declaration of an identifier for an object has file scope and no storage-class specifier, its linkage is external.

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

If the declaration of a file scope identifier for an object or a function contains the storage-class specifier static, the identifier has internal linkage.

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

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


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

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

这会让你走得更远,而你实际需要在不同文件之间共享变量的罕见情况是另一个 story/advanced 主题。

Global Variable in C by default corresponds to static storage class but has external linkage. Does this mean it is partially static and partially extern?

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

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

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

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

  • 静态存储持续时间意味着对象的内存在整个程序执行过程中都被保留。
  • 在声明中使用 static 关键字,除了如下所示,都提供对象静态存储持续时间,并且在函数外部的声明中,提供标识符内部链接。
  • 在参数声明中的下标标记内使用 static 关键字,如 void foo(int a[static 3]),表示参数至少指向规定数量的元素。
  • 静态断言,使用 _Static_assert,提供 compile-time 测试(这可以帮助检测错误或确保程序正在按预期设置编译)。

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