【问题标题】:Error: redefinition of "a static variable" in C header files错误:在 C 头文件中重新定义“静态变量”
【发布时间】:2018-12-10 16:01:16
【问题描述】:

我在两个不同的文件中声明了一些静态变量(例如 var1 和 var2)。两个文件中的变量名称相同。有些变量(比如 var1)没有在它们的声明中初始化,有些是(var2),如下所示。

file1.h

static bool var1;
static bool var2 = false;

file2.h

static bool var1;
static bool var2 = false;

根据我的理解,静态变量仅限于声明它们的 c 文件(或 h 文件),因此在多个头文件中使用相同的变量名应该是安全的。但是当我编译代码时,我得到错误“redefinition of var2”,仅针对已初始化的变量。

  1. 为什么这个错误只发生在 var2 上?
  2. 我的实现还好吗?

编辑: 由于有人提到使用 extern 关键字,我想澄清一下 var1 和 var2 在不同的 c 文件中应该有不同的值,并且应该仅限于它们各自的文件,

【问题讨论】:

  • 头文件被复制到.c文件中。如果将两个标题都包含在同一个文件中,则会有多个定义。
  • var1只有一个暂定定义。
  • 在头文件中使用externWhen to use extern in C++

标签: c variables static header-files static-initialization


【解决方案1】:

没有。 var1 的多重声明是可以的,但var2 的多重定义 不是。你不能两次初始化一个变量......即使值相同。

我使用预处理器保护来解决此类问题,例如:

#if !defined(MY_APP__VARS_DEFINED)
static int var1, var2=0;
#define MY_APP__VARS_DEFINED
#endif

即便如此,我也不建议在多个头文件中复制定义。这是一个维护问题。迟早,有人可能会更改一个标头中的初始值,而找不到定义它的所有其他标头。这也使重命名(“重构”)变得更加困难。 (...并且违反了DRY Principle。)

不过,您可能需要重新考虑您的设计。全局变量通常会导致应用程序脆弱;更难维护且容易损坏。

【讨论】:

  • 实际上这些变量应该在不同的c文件中保存不同的值,但是由于信息几乎相似,我将它们命名为相同,它们应该在一个c文件中是全局的,但不应该是对整个程序来说是全局的,这不是为什么使用 static 关键字吗?就像我们在多个函数中使用同名的局部变量(例如,for循环中的'i'),我希望在多个编译单元中使用相同的全局变量,这可能吗?
  • @Salman 是的,这是可能的。只需使用如图所示的预处理器保护思想。初始化 all 这样的变量可能是个好主意;为“未初始化”变量提供可识别的无意义值(如 0xDEADDEAD 或类似的值)。如果需要,我仍然会将声明放在其他头文件可以包含的通用头文件中。单点维护、DRY、一个放置生成开发文档的 cmets 的地方等
【解决方案2】:

如果一个源文件同时包含 file1.h 和 file2.h,它将有多个 var2 定义。这就是导致错误的原因。

与其在头文件中声明/定义这些静态变量,不如将它们直接放在必要的C源文件中。这样您就不必处理多个定义。

【讨论】:

    【解决方案3】:

    为什么这个错误只发生在 var2 上? 如果你在同一个源文件 test.cpp 中包含 file1.hfile2.h 那么 var2 将有两个定义并且编译器无法选择采取哪一个并引发错误。

    为了避免这种情况,在标题 .h 文件中将 var2 声明为 extern 并在相应的源 .cpp 文件中定义。

    虽然在var1 的情况下,它只是declaration 而不是definition,因此它不会引发错误,即可以进行多个声明。

    还有static 声明之类的

    static bool var1;
    

    表示变量var1仅在当前编译单元中可见。

    旁注,static 变量具有内部链接,即它对其他翻译单元隐藏了 static 变量。虽然static 变量在多个翻译单元中可以是defined

    并且extern 变量具有外部链接,即extern 变量将对其他翻译单元可见,但extern 变量应仅在一个翻译单元中定义。

    【讨论】:

    • 实际上这些变量应该在不同的c文件中保存不同的值,但是由于信息几乎相似,我将它们命名为相同,它们应该在一个c文件中是全局的,但不应该是对整个程序来说是全局的,这不是为什么使用 static 关键字吗?就像我们在多个函数中使用同名的局部变量(例如,for循环中的'i'),我希望在多个编译单元中使用相同的全局变量,这可能吗?
    猜你喜欢
    • 2013-08-04
    • 2016-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-12
    相关资源
    最近更新 更多