小智 15
在C和C++中,您可以通过在声明前面使用static关键字来创建一个全局变量,只能从声明它的文件中访问它.可以从编译到程序中的任何C或C++文件访问不使用static关键字的Globals.
在C++中不推荐使用静态全局方法,而是使用匿名命名空间.放置在匿名命名空间内的任何声明也只能从该文件中访问.
C++程序一次编译一个翻译单元(基本上这意味着每个.cpp文件是独立编译的).
默认情况下,变量都没有const,功能不inline和typedef■找内部链接:这意味着他们不给其他翻译单元可见.如果其他翻译单元引用具有内部链接的符号(在声明它之后,需要extern变量的关键字),链接器将无法找到它们.
要明确要求内部链接,请使用关键字,static或者更好地使用未命名的命名空间.
注意:这些规则适用于 C++ 和 C 一样,与类/结构/命名空间范围有关。(我没有注意到问题是关于 C++,而不是 C。)
请记住(在大多数情况下)C 源文件被编译为目标文件。目标文件有一个“导出”表,它告诉链接器(在链接时)它提供了什么符号。符号是指代函数或变量(在大多数情况下)的名称(其确切名称取决于 ABI)。
当您在 C 源文件中声明全局变量时,如下所示:
// fileA.c
int hello = 42;
void printMessage() {
printf("Hello, %d world(s)!\n", hello);
}
Run Code Online (Sandbox Code Playgroud)
hello并printMessage出口。当一个 C 目标文件请求一个名为“ hello”的符号(假设一个简单的 ABI)时,链接器将它与hello导出的fileA.c.
现在是另一种情况。当您像这样声明文件局部变量时:
// fileB.c
static int world = 9001;
static void messagePrint() {
printf("It's over %d!\n", world);
}
Run Code Online (Sandbox Code Playgroud)
world而messagePrint在没有出口。当 C 目标文件请求名为“ hello”的符号时,链接器无法将其与helloof连接,fileB.c因为在fileB.obj(或其他)中没有关于它的信息。
怎么可能messagePrint知道world呢?两者都在同一个翻译单元中。范围在这里接管。我相信您会通过 Google找到很多关于范围的信息。
(符号名称是否与 C 中的函数/变量名称标准相匹配?我知道它与 C++ 不同(名称修改没有标准化),这就是我首先提到 ABI 的原因。)
((如果 ABI 是正确的术语,甚至?;P))