C头文件中的全局变量初始化

Global variables initialization in C header file

我想知道为什么在 C 的多个源中包含的头文件中声明全局变量是有效的

#ifndef INC_MAIN_H_
#define INC_MAIN_H_

int my_var;

#endif 

但是为其分配默认值不起作用:

#ifndef INC_MAIN_H_
#define INC_MAIN_H_

int my_var = 0;

#endif 

它在我包含这个的每个文件中显示多个编译错误main.h

multiple definition of `my_var'; app/src/testfile.o:app/inc/main.h:4: first defined here

我知道以这种方式声明全局变量不是最佳做法,但我不明白为什么添加赋值会导致编译错误,而且我找不到明确的答案。

对于您正在使用的构建工具和开关,int my_var; 的行为主要类似于声明,而不是定义。 object 标识符的多重声明是允许的。

int my_var = 0;是一个定义。应该只有一个定义。

由于 C 使用和开发的历史,int my_var; 在技术上是一个 暂定定义 。如果翻译单元(正在编译的源文件,包括它包含的所有文件)中没有my_var的正则定义,则作为正则定义。

但是,当您将它放在包含在多个源文件中的 header 文件中时,您就有了多个定义。当有多个具有外部链接的相同 object 标识符的定义时,C 标准没有定义行为。

当存在多个正则定义时,您的构建工具会报错。然而,他们以不同的方式对待来自暂定定义的定义:他们允许它们并将它们合并成一个单一的定义。同样,这是由于 C 的开发和使用历史。此外,这种行为最近在 GCC 中发生了变化。在 GCC 版本 10 之前,默认情况下合并临时定义,如上所述。使用 GCC 10 及更高版本,临时定义不会合并,多个定义将导致错误。可以使用开关 -fcommon.

请求旧行为

为了避免暂定定义,你应该在header中声明标识符为extern int my_var;,这只是一个声明而不是暂定定义,你应该只有一个源文件包含int my_var = 0;,这是常规定义,不是暂定定义。

附加信息是 here, here, and here