一个翻译单元如何访问另一个翻译单元的全局作用域?
How can a translation unit access the global scope of another translation unit?
我一直在阅读链接器是如何工作的,以及围绕这个过程的一切,以解释我在这个(链接)问题中的问题(很短,抱歉关于参考,但它是相关的)。
: 如果在头文件中我有一个变量声明(使用extern),并且我想在多个源文件中使用这个变量(当然包括每个源文件中的头文件),我必须在某个地方为这个变量提供一个定义。问题是,如果我在一些源文件的main函数中提供了一个定义,例如,其他文件仍然没有"看到"这个定义(这会导致链接错误)。如果我在一个全局作用域中定义这个外部变量,它可以正常工作,并且每个人都可以看到它。
为什么?其他文件如何访问另一个文件的全局作用域?全局作用域变量不危险吗?将变量定义放在其他什么作用域中可以解决这样的链接错误?有人在头文件中使用这样的外部变量声明吗?出于什么目的?
编辑:确切的示例情况是在我在开头发布的链接
一些说明:
你所说的"文件"更恰当地称为翻译单元。涉及多少文件并不重要。实际上,同一个文件可以被重新编译(比如使用不同的#定义,等等)
有了这个术语,我们现在可以重新表述你的问题:"一个翻译单元如何访问另一个翻译单元的全局作用域"?引用自维基百科关于链接的文章:
如果名称具有外部链接,则名称所表示的实体可以从另一个翻译单元使用相同名称的不同声明引用,也可以从同一翻译单元内的其他作用域使用不同声明引用。
换句话说:通过确保该名称作为外部链接,它在全局作用域中,并且对于程序是全局的,而不是翻译单元。
剩余问题:
全局作用域变量不危险吗?
我永远不会用"危险"这个词来描述它们,因为我认为某些标准库函数有安全缺陷,等等。但我要说的是,这通常会导致设计非常糟糕的代码,特别是在全局变量的情况下,在多线程代码中会出现很多令人头疼的问题。一个好的规则是:避免使用它们,除非你有很好的理由不这样做。
如何避免链接错误(在其他范围内)
这里没有其他神奇的声明:它要么在翻译单元外可见(外部),要么不可见(静态)。您可能会问:"让其他模块访问该变量的正确方法是什么?"答案是:写一个访问器函数(或者更好的是,一个用方法管理数据的类)。
谁在用这些东西,为了什么目的?
总是一个热议的话题。许多人建议完全避免,但你很难在一个足够大的项目中不找到外部人员。最好的理由通常归结为纯粹主义者所忽略的事情:与遗留系统的兼容性、性能、调试器和其他内省工具的易于访问……或者,当然,只是因为它很容易,它被理解,并且它只是工作。
当您放置变量in the main function
时,您定义了一个在该函数中可见的局部变量。
您必须在一个源文件的文件范围内定义变量
- 不同翻译单元中不可重载的非内联函数定义
- 为什么未命名的结构内联变量在每个翻译单元中没有相同的地址?
- 如何执行 cppcheck 交叉翻译单元 (CTU) 静态分析?
- 模板变量是否允许在多个翻译单元中并有效合并?
- 是否允许类在程序中的不同翻译单元之间具有不同的定义?
- 为什么具有静态存储持续时间的同一内联变量在包含在 VS2017 编译的两个翻译单元中时会构造和销毁两次
- 为什么不同的翻译单元没有独立和沙盒的内存空间?
- 为什么编译器不在同一翻译单元中警告 ODR 违规
- 静态变量在同一个翻译单元中被静态方法使用时是否保证被初始化?
- 来自不同翻译单元的函数会干扰吗?
- 如何在C++中的不同翻译单元之间共享枚举的实例
- 在C++中声明"interface",而不是将其 vtable 发送到每个翻译单元
- MSVC 2017 在单个翻译单元中违反静态初始化顺序
- 在不同的翻译单元中启动全局变量(涉及链接)
- 链接器如何处理跨翻译单元的相同模板实例化
- 在不同翻译单元中具有静态存储持续时间的依赖非局部常量浮点变量的常量初始化
- 翻译单元的数量与CPP文件的数量
- GCC 6.3.0 中的 ODR 冲突,类型在两个单独的翻译单元中定义
- 为什么结构和类定义可以在多个翻译单元上重复?
- 如果在同一翻译单元中调用功能,为什么需要搬迁