静态变量具有文件范围。假设我有以下两个文件:
我在两个头文件中都声明了静态变量
static int Var1
。 file1.h
和 file2.h
都包含在 main.cpp
文件中。
我这样做是因为静态变量将具有文件范围,因此它们不会相互冲突。 但编译后我发现它显示冲突。
现在静态变量的行为就像一个
extern
变量。另一方面,如果我在两个 .cpp 文件中声明静态变量,它编译得很好。
我无法理解这种行为。
任何人都可以解释一下范围和链接在这种情况下是如何工作的吗?
静态变量是编译单元的本地变量。 编译单元基本上是一个
.cpp
文件,其中插入了 .h
文件的内容来代替每个 #include
指令。
现在,在一个编译单元中不能有两个同名的全局变量。这就是您的情况所发生的情况:
main.cpp
包括 file1.h
和 file.h
,两个标头中的每一个都定义了自己的 Var1
。
如果逻辑上这是两个不同的变量,请给它们不同的名称(或将它们放在不同的命名空间中)。
如果这些是相同的变量,请将其移至单独的头文件
var1.h
中,并包含 var1.h
和 file1.h
中的 file2.h
,不要忘记 var1.h
中的 #include Guard。
静态变量具有翻译单元范围(通常是
.c
或 .cpp
文件),但 #include
指令只是逐字复制文件的文本,并且不会创建另一个翻译单元。预处理后,这个:
#include "file1.h"
#include "file2.h"
会变成这样:
/* file1.h contents */
static int Var1;
/* file2.h contents */
static int Var1;
如您所知,这是无效的。
假设静态变量
static int Var1
在两个标头中都处于全局范围内,并且将两个标头都包含在main.cpp
中。现在,首先预处理器将包含文件的内容复制到main.cpp
。由于在 main.cpp
处有 Var1
在同一范围内声明了两次,因此会出现多重声明错误。 (即,一个由预处理器从 file1.h
复制,另一种形式 file2.h
)
每个源文件都是单独编译的。现在,当您在源文件中单独声明时,每个源文件都不知道另一个同名源文件中存在另一个静态变量。所以,编译器不会报告错误。如果您希望在源文件之间共享变量,您可以将其标记为 extern。