繁体   English   中英

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

[英]C++ extern keyword on functions. Why no just include the header file?

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

extern void foo();

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

1)为什么不#include声明此函数的头?

2)链接器如何知道在链接时寻找函数的位置?

编辑:也许我应该澄清上面的声明然后使用该函数

foo();

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

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

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

不,这意味着函数foo是通过外部链接声明的。 外部链接意味着名称foo指的是整个程序中的相同功能。 定义函数无关紧要。 它可以在此翻译单元中定义。 它可以在其他翻译单元中定义。

使用示例中显示的extern关键字是多余的。 函数默认情况下始终具有外部链接。 以上是100%相当于

void foo();

对于链接器,当链接器将程序链接在一起时,它只是在任何地方查找。 它查找所有定义,直到找到foo的定义。

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

extern关键字的另一个用法是这样的:

extern "C" void foo();

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

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

使用函数原型是可以的,但很容易弄错。 重新定义函数实现时,您将获得的链接器错误并不容易诊断。 链接器不知道在哪里查找,为您提供一个包含函数定义的目标文件以保持其满意是您的工作。

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

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

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

例1:

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

$> ld ao -la -lb

将导致搜索未定义的符号。 此后ld将从左到右遍历libs以搜索这些符号,并在libb中找到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搜索属于该组的所有库中的所有符号。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM