C++函数上的 extern 关键字。为什么不只包含头文件?

发布于 2024-08-28 08:52:56 字数 256 浏览 8 评论 0原文

如果我理解正确的话,这意味着

extern void foo();

函数 foo 是在另一个翻译单元中声明的。

1)为什么不只是 #include 声明该函数的标头?

2)链接器如何知道在链接时去哪里寻找函数?

编辑:也许我应该澄清一下,上面的声明后面跟着使用函数

foo();

It 从未在此翻译单元中定义。

If I understand it correctly this means

extern void foo();

that the function foo is declared in another translation unit.

1) Why not just #include the header in which this function is declared?

2) How does the linker know where to look for function at linking time?

edit: Maybe I should clarify that the above declaration is then followed by using the function

foo();

It is never defined in this translation unit.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

醉生梦死 2024-09-04 08:52:56

1)它可能没有头文件。但是,是的,一般来说,对于大型项目,如果多个翻译单元要使用该函数,则应该有一个头文件(不要重复)。

2) 链接器搜索它被告知的所有目标文件和库,以查找函数和其他符号。

1) It may not have a header file. But yes, in general, for large projects, you should have a header file if multiple translation units are going to use that function (don't repeat yourself).

2) The linker searches through all the object files and libraries it was told about to find functions and other symbols.

青萝楚歌 2024-09-04 08:52:56

不,这意味着函数 foo 是通过外部链接声明的。外部链接意味着名称foo在整个程序中引用同一个函数。函数定义在哪里并不重要。它可以在这个翻译单元中定义。它可以在其他翻译单元中定义。

如示例中所示使用 extern 关键字是多余的。默认情况下,函数始终具有外部链接。上面的内容 100% 等同

void foo();

于链接器,当链接器将程序链接在一起时,它只是看起来到处。它会查找所有定义,直到找到 foo 的定义。

No, this means that function foo is declared with external linkage. External linkage means that name foo refers to the same function in the entire program. Where the function is defined does not matter. It can be defined in this translation unit. It can be defined in other translation unit.

Using extern keyword as shown in your example is superfluous. Functions always have external linkage by default. The above is 100% equivalent to just

void foo();

As for the linker, when the linker links the program together it simply looks everywhere. It looks through all definitions until it finds the definition for foo.

余生共白头 2024-09-04 08:52:56

正如其他人已经指出的,extern 关键字用于声明名称(变量或函数)具有外部链接,这意味着该名称引用整个程序中的同一对象。此外,这是在文件范围内定义的变量和函数的默认值,因此这种用法是多余的。

extern 关键字还有另一种用法,如下所示:

extern "C" void foo();

这意味着函数 foo 将使用 C 链接约定进行链接(可能是因为这是在 C 库中定义的函数,或者是预期的函数)由 C 程序调用)。

As others have already stated, the extern keyword is used to state the name (a variable or function) has external linkage, meaning the name refers to the same object in the entire program. Also, this is the default for variables and functions defined at the file scope, so this usage is superfluous.

There's another use of the extern keyword that goes like this:

extern "C" void foo();

This means the function foo will be linked using the C conventions for linkage (maybe because this is a function defined in a C library or is a function intended to be called by C programs).

沉溺在你眼里的海 2024-09-04 08:52:56

它已经意味着没有 extern 关键字。函数默认具有外部链接,除非您将它们声明为静态。

使用函数原型是可以的,但是很容易出错。当您重新定义函数实现时,您将得到的链接器错误并不那么容易诊断。链接器不知道去哪里查找,您的工作就是给它一个包含函数定义的目标文件以使其保持满意。

It already means that without the extern keyword. Functions have external linkage by default, unless you declare them static.

Using function prototypes is okay but it is easy get it wrong. The linker error you'll get isn't that easy to diagnose when you redefine the function implementation. The linker doesn't know where to look, it is your job to give it an object file that contains the function definition to keep it happy.

心凉 2024-09-04 08:52:56

1)我不知道为什么我需要这个功能。也许其他人可以介入。2

) 链接器通过遍历所有目标文件并检查每个目标文件内的符号来确定这一点。我假设根据您的链接器,确切的搜索顺序可能会有所不同。

对于 GNU binutils 的 ld,从左到右搜索包含缺失符号的对象后出现在链接器命令行中的所有对象文件和库,并选择第一个找到的符号。

示例 1:

  • ao -- 使用 foo()、bar()
  • liba -- 提供 bar()
  • libb -- 提供 foo()

$> ld ao -la -lb

将导致在 ao 中搜索未定义的符号。此后 ld 将从左到右遍历库来搜索这些符号,并会在 liba 中找到 bar,在 libb 中找到 foo。

这可能会导致循环依赖出现奇怪的问题:

示例 2:

  • ao -- 使用 bar()
  • liba -- 提供 bar(),使用 foo()
  • libb -- 提供 foo(),使用 bar( )

现在,liba 和 libb 之间存在循环依赖关系,链接将失败:

$> ld ao -la -lb

因为在搜索 libb 中未定义的符号时,ld 会确定 -lb 右侧没有其他 lib 提供该符号。这至少可以通过两种方式修复:

1)链接 liba 两次:
$> ld ao -la -lb -la

2) 使用ld的分组功能
$> ld ao --start-group -la -lb --end-group

在情况 2) 中,分组告诉 ld 搜索属于该组的所有库中的所有符号。

1) I don't know why I'd need this for a function. Maybe someone else can step in.

2) The linker determines this by going through all object files and checking the symbols inside each object file. I assume that depending on your linker, the exact search order might vary.

For GNU binutils' ld all object files and libraries that appear in the linker command line after the object containing the missing symbol are searched from left to right and the first found symbol is picked.

Example 1:

  • a.o -- uses foo(), bar()
  • liba -- provides bar()
  • libb -- provides foo()

$> ld a.o -la -lb

will result in a.o being searched for undefined symbols. Thereafter ld will go through the libs from left to right to search for these symbols and will find bar in liba and foo in libb.

This may lead to strange problems upon circular dependencies:

Example 2:

  • a.o -- uses bar()
  • liba -- provides bar(), uses foo()
  • libb -- provides foo(), uses bar()

Now, there is a circular dependency between liba and libb and linking will fail:

$> ld a.o -la -lb

because when searching through the undefined symbols in libb, ld will determine that there is no other lib to the right of -lb that provides this symbol. This may be fixed in at least two ways:

1) link liba twice:
$> ld a.o -la -lb -la

2) use ld's grouping feature
$> ld a.o --start-group -la -lb --end-group

In case 2), the grouping tells ld to search through all symbols in all libs belonging to this group.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文