头文件中声明的变量是否将变量的单独副本提供给每个包含的.c文件? [英] Does variables declared in a header file give separate copies of the variables to each included .c file?

查看:59
本文介绍了头文件中声明的变量是否将变量的单独副本提供给每个包含的.c文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设有两个源文件, file_1.c file_2.c ,它们包含相同的头文件file.h.file.h具有变量 int 变量.一旦 file_1.c file_2.c 包含file.h, file_1.c file_2.c 是否具有变量变量的单独副本,还是它们共享相同的副本?

Suppose there are two source files, file_1.c and file_2.c , which include the same header file file.h. file.h have a variable int var. Once file_1.c and file_2.c include file.h, does file_1.c and file_2.c have separate copies of the variable var, or does they share the same ?

推荐答案

让我们从完全由C标准定义的案例开始.如果 file.h 包含 extern int x; ,它将声明一个标识符 x 来引用某些 int 对象.此声明是编译期间 file_1.c file_2.c 各自的一部分,并且通过 linkage ,根据C 2018 6.2.2.

Let’s start with a case that is fully defined by the C standard. If file.h contains extern int x;, it declares an identifier x to refer to some int object. This declaration is a part of each of file_1.c and file_2.c during compilation, and it is "made to refer to the same object" by linkage, per C 2018 6.2.2.

在这种情况下, extern int x; 只是一个未定义 x 的声明.其他一些声明必须定义 x .这可以通过将 int x; int x = value; 放在 file_1.c file_2.c 中来完成>.这样,您的问题的答案将是多个源文件中的 extern int x; 将指向同一对象.

In this case, extern int x; is merely a declaration that does not define x. Some other declaration must define x. This could be done by putting int x; or int x = value; in file_1.c or file_2.c. Then the answer to your question would be that extern int x; in multiple source files would refer to the same object.

在您询问的情况下,使用 file.h 中的 int x; ,C标准并未完全定义该行为.根据C 2018 6.9.2,这是一个临时定义.如果没有 x 的常规定义,则C标准表示,该临时定义导致定义 x 就像将其初始化为零一样.(相反,带有初始化器的声明,例如 int x = 0; ,是常规定义,而不是临时定义.)

In the case you ask about, with int x; in file.h, the behavior is not fully defined by the C standard. Per C 2018 6.9.2, this is a tentative definition. If there is no regular definition of x, the C standard says the tentative definition results in x being defined as if it were initialized to zero. (In contrast, a declaration with an initializers, such as int x = 0;, is a regular definition, not a tentative definition.)

在这种情况下, file_1.c file_2.c 都定义了 x .因此,每个文件都有其自己的定义.然后,C标准没有按照6.9 5定义行为,该行为表示此类标识符的定义不得超过一个定义(如果在表达式中实际使用,则应定义为一个定义).

In that case, both file_1.c and file_2.c define x. So each file have its own definition. Then the C standard does not define the behavior, per 6.9 5, which says there shall be no more than one definition for such an identifier (and exactly one if it is actually used in an expression).

由于C标准未定义行为,因此C实现可以.直到最近,GCC,Clang和Unix工具都将暂定定义与常规定义区别对待.允许使用多个临时定义,并将它们合并形成一个定义.因此,在这种情况下,对您的问题的回答是混杂的:当 int x; 出现在多个源文件中时,名义上在编译过程中对C标准的某些解释中名义上是指不同的"对象,但是要链接将其解析为同一对象.

Since the C standard does not define the behavior, C implementations may. Until recently, GCC, Clang, and Unix tools treated tentative definitions differently from regular definitions. Multiple tentative definitions were allowed, and they were coalesced to form one definition. So, the answer to your question in this case is mixed: when int x; appears in multiple source files, it nominally refers to "different" objects in some interpretation of the C standard during compilation, but linking resolves it to the same object.

GCC的最新版本更改了此行为.默认情况下,暂定定义更像常规定义一样对待,因此多个暂定定义将导致链接错误.在这种情况下,您的问题的答案是,当 int x; 出现在多个源文件中时,它引用了不同的对象,这将阻止程序链接.

Recent versions of GCC changed this behavior. By default, tentative definitions are treated more like regular definitions, so multiple tentative definitions will result in a link error. In this case, the answer to your question is that when int x; appears in multiple source files, it refers to different objects, and this prevents the program from linking.

(GCC中的此更改始于版本10.命令行开关 -fcommon 或通过将属性 __ attribute __((__ common __))应用于标识符.)

(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.)

这篇关于头文件中声明的变量是否将变量的单独副本提供给每个包含的.c文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆