在头文件中声明的变量是否为每个包含头文件的.c文件给予变量的单独副本?

kpbwa7wx  于 2022-12-03  发布在  其他
关注(0)|答案(1)|浏览(186)

假设有两个源文件file_1.cfile_2.c,它们包含相同的头文件file.hfile.h有一个变量int var。一旦file_1.cfile_2.c包含file.hfile_1.cfile_2.c是否有变量var的单独副本,或者它们共享同一个副本?

5n0oy7gb

5n0oy7gb1#

让我们从一个完全由C标准定义的例子开始。如果file.h包含extern int x;,它声明一个标识符x来引用某个int对象。这个声明在编译过程中是file_1.cfile_2.c的一部分,并且根据C 2018 6.2.2,它通过 linkage“使其引用同一个对象”。
在这种情况下,extern int x;仅仅是一个没有定义x的声明。其他声明必须定义x。这可以通过将int x;int x = value;放在file_1.cfile_2.c中来完成。那么对您问题的回答将是多个源文件中的extern int x;将引用同一个对象。
在您询问file.h中的int x;的情况下,C标准没有完全定义该行为。根据C 2018 6.9.2,这是一个暂定定义。如果没有x的常规定义,C标准认为暂定定义导致x被定义为好像它被初始化为零。(相反地,具有初始设定式的宣告,例如int x = 0;,是一般定义,而不是暂定定义)。
在这种情况下,file_1.cfile_2.c都定义了x。因此,每个文件都有自己的定义。然后,C标准没有定义行为,根据6.9 5,这意味着这样的标识符不应有超过一个定义(如果它实际上在表达式中使用,则正好是一个)。
由于C标准没有定义行为,C实现可能会定义。直到最近,愚者、Clang和Unix工具都将临时定义与常规定义区别对待。允许多个临时定义,并且它们被合并形成一个定义。因此,在这种情况下,对您的问题的答案是混合的:当int x;出现在多个源文件中时,在编译过程中,名义上它指的是C标准的某些解释中的“不同”对象,但链接将其解析为同一对象。
愚者的最新版本改变了这种行为。默认情况下,暂定定义更像常规定义,因此多个暂定定义将导致链接错误。在这种情况下,您问题的答案是,当int x;出现在多个源文件中时,它引用不同的对象,这将阻止程序链接。
(This change in GCC started in version 10. The old behavior can be requested with the command-line switch -fcommon or by applying the attribute __attribute__((__common__)) to an identifier.)

相关问题