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