如何让一个翻译单元访问另一个翻译单元的全局作用域?

3
我一直在阅读关于链接器的工作原理以及围绕这个过程的所有内容,以便在此问题中解释我的问题(它很短,抱歉引用,但它是相关的)。
问题是: 如果在头文件中有一个变量声明(使用extern),并且我想在多个源文件中使用此变量(在每个源文件中包含头文件),我必须在某个地方提供此变量的定义。问题在于,如果我在某些源文件的主函数中提供定义,其他文件仍然看不到这个定义(这导致链接错误)。如果我在全局作用域之一中定义此外部变量,它可以正常工作,而且每个人都能看到它。
为什么?其他文件如何访问另一个文件的全局作用域?全局作用域变量不危险吗?将变量定义放在哪个范围内可以解决这样的链接错误?有人在头文件中使用这样的外部变量声明,目的是什么?
编辑:确切的示例情况在我在开头发布的链接中。

我不太确定你想要解释什么。你具体是在哪里尝试定义变量?提供一个定义变量的示例会更好。 - goji
抱歉,我无法访问链接。请提供文本以供翻译。 - lekroif
在您实际问题的代码中,没有声明,这在被接受的答案中是正确的,您想将变量定义从main()函数体外移动到main()函数体内吗?如果是这样,那么哈珀的答案是完全正确的。该变量仅存在于该函数内部。 - goji
2个回答

5
一些澄清:
你所称的“文件”更应该称为“翻译单元”。涉及的文件数量并不重要。事实上,同一文件可以重新编译(例如使用不同的#define等)。
有了这个术语,我们现在可以重新表述您的问题:“如何让一个翻译单元访问另一个翻译单元的全局作用域”?
引用维基百科关于链接的文章:
如果名称具有外部链接,则可以使用该名称的不同声明从另一个翻译单元引用名称所表示的实体,并使用不同声明从同一翻译单元中的其他范围引用名称所表示的实体。
换句话说:通过确保该名称具有外部链接,它位于全局作用域中,这是针对程序而不是翻译单元的全局作用域。
您剩下的问题:
  1. 全局作用域变量不危险吗?

    我不会用“危险”这个词来形容它们,就像我也不会形容某些标准库函数存在安全漏洞等。但我会说,它们往往会导致代码设计非常糟糕,在特定情况下,例如全局变量,会在多线程代码中带来许多麻烦。一个好的规则是:除非你有充分的理由,否则避免使用它们。

  2. 如何避免链接错误(在其他范围内)

    没有其他神奇的声明:要么可见于翻译单元之外(外部),要么不可见(静态)。你可能想问的是:“让其他模块访问变量的正确方法是什么?”答案是:编写一个访问器函数(或者更好的是,使用方法管理该数据的类)。

  3. 谁使用这些东西以及出于什么目的?

    总是一个备受争议的话题。许多人建议完全避免使用,但在足够大的项目中,很难不找到一个extern。最好的原因通常归结为那些纯粹主义者忽略的事情:与传统系统的兼容性、性能、易于调试器和其他内省工具访问……或者,当然,只是因为它很容易,它被理解了,并且它起作用。


2
除了1.之外:在错误的手中,锤子和全局变量一样危险,但有时锤子非常方便。 - akira

3
当你在主函数中放置一个变量时,你定义了一个在该函数中可见的局部变量。
你必须在一个源文件中的文件作用域内定义该变量。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接