5

为什么结构的双重声明会导致编译错误,而函数的双重定义会导致链接错误

4

4 回答 4

4

因为函数定义在链接时包含在可执行文件中,但声明或语法检查都在编译时完成

当您调用任何函数并且编译器无法找到函数的声明时,还要考虑一件事,然后它将生成警告为implicit declaration of func().

为了删除这个警告信息,我们提供了 func 的前向声明,int func();它编译时没有任何警告信息。

你认为为什么会发生这种情况?发生这种情况是因为编译器没有找到该func()符号。根据语言语法使代码无错误完全取决于编译器。

但是最终可执行文件的构建是在链接时完成的,然后链接器开始寻找函数定义func(),如果找到则很好,如果没有.. 然后Linker error

could not have resolved external symbol _func()

注意:任何外部符号都在链接时解析

在 gcc 上仅用于编译使用:(这可能因编译器而异)

gcc -Werror -c test.c --> 生成test.o文件

然后尝试链接它并使其可执行

gcc -Werror -o test test.o-->test是可执行的

于 2012-11-14T09:56:01.777 回答
2

该标准没有说明何时应该报告错误 - 这取决于编译器,但基本上是因为那是错误被捕获的时间

首先,编译器解析文件。很容易看出 a structorclass是否在同一个翻译单元中被多次定义(只是这是一个错误,在翻译单元之间你可以有多个类类型定义),因为它处理那个翻译单元。

其次,它将目标文件链接在一起(链接)。直到现在它才能知道同一个符号被导出了多次,因为那是错误发生的时候。

于 2012-11-14T10:01:18.550 回答
2

编译程序时,编译器需要知道要使用的结构的确切定义。但是我们只需要在尝试链接程序时才知道要使用哪个确切的功能。

因此,如果一个结构被定义了两次,编译器在编译过程中会感到困惑,因此会在编译时抱怨。

对于编译期间的函数,您可以有多个定义,但只有在链接期间才会出现混淆,因此在链接期间会出现问题。

于 2012-11-14T10:01:33.343 回答
1

你说的不一定是真的。

如果你在头文件中“内联”函数定义,然后在编译单元中写入它的定义,你会得到一个错误

...already has a definition.

您所指的情况是当两个不同的编译单元定义(或查看定义)相同的函数时,因此在任何单个编译单元中都没有编译错误,而是它们的组合导致了链接错误。

顺便注意一下,这就是关键字inline真正发挥作用的地方。对于头文件中定义的非模板函数,如果使用inline关键字,则意味着定义该函数时可以存在多个编译单元。它实际上并不能保证编译器会内联它。

于 2012-11-14T10:07:00.380 回答