【问题标题】:Do I have to include the C file that contains the definition for a function?我是否必须包含包含函数定义的 C 文件?
【发布时间】:2018-07-26 00:43:36
【问题描述】:

所以我一直在做一些阅读,但我仍然在 C 中遇到 extern 关键字的问题。

例如: 我有一个名为: main.c 的文件,在其中我声明了一个函数 int add(int a, int b); (在使用之前)。但是,函数的定义位于 math.c 中。这是否意味着我必须在 main.c (#include math.c/h) 或 main.h 文件中包含 math.c 和/或 math.h 文件才能使用该函数而不会导致编译时错误?或者仅仅声明函数 int add(int a, int b) 就足够了吗?

简而言之:我是否必须包含定义函数声明的文件?

此外,如果仅仅声明函数就足够了,这是一种好的做法,还是链接器会处理它?

谢谢。

【问题讨论】:

  • 一般来说,从不使用#include *.c 文件。但是,如果您想使用 libm 库中的函数,那么最简单的方法是使用:#include >math.h> 但是,如果您只是想为自己做更多的工作,那么将该函数的原型写入您的main.c文件
  • 正如 user3629249 所说,您不包含 *.c 文件。但是您需要将 *.h 文件包含到您的主文件中(我假设您有一个包含 math.h 声明的文件)并且您需要将 math.c 与 main.c 一起编译,即gcc main.c math.c -o New_file
  • 对不起,我认为我的问题被误解了。这与功能本身无关,也与所涉及的数学库无关。选择文件名是为了说明一个场景。我真正要问的问题是链接器,以及具有给定声明定义的文件是否可能包含在使用该函数的文件中。

标签: c linker include declaration extern


【解决方案1】:

您应该在“main.c”中包含“math.h”并将add的定义放在“math.h”中:int add(int a, int b);

然后在“math.c”中包含“math.h”,并通过创建执行计算的代码在该文件中实际声明add

然后编译器将两个 .c 文件独立编译为 Linux/MacOS 下的 .o 文件,或 Windows 下的 .obj 文件。然后链接器获取这两个 .o / .obj 文件并将它们链接在一起以生成完整的可执行文件。

作为一般规则,具有.h 扩展名的头文件旨在包含在多个.c 文件中,并提供有关可以在相应.c 文件中找到的内容的信息。所以math.h 包含了所谓的add 的原型,这使得main.c 可以了解该功能,因此它能够正确使用它,而math.c 包含实际代码。

虽然不是绝对必需的,但从长远来看,遵守此约定将使您的喜欢变得更容易,尤其是当您有包含许多 .c.h 文件的大型项目时。这就是为什么您会发现它几乎被用于您下载的所有开源项目中。

-- 编辑--

此外,作为一般规则,不要在.c 文件中直接包含外部定义。始终尝试将它们放在.h 头文件中。如果您的项目中有 100 个或更多 .c 文件,并且您决定需要更改函数的原型,那么将它们直接放在 .c 文件中会造成维护噩梦。您现在必须编辑无数单独的 .c 文件,而不是编辑单个 .h .c 对。这将非常容易出错。

【讨论】:

  • 我想我有点理解你所说的前两个陈述,但是由于使用了“那个”这个词,你是否指的是前者还是有点不清楚在所述声明中的后一个文件。我希望您澄清以下内容[基于线程示例场景]。我在 main.c 中声明了 extern 函数 int add(...),但定义位于 math.c 中。但是我没有以任何方式明确地在代码中“加入”(#include)这两个文件(甚至不是通过 .h 文件)。声明会与文件的定义匹配吗?
  • 现在应该更清楚了:我已明确将“math.h”命名为包含add 定义的文件。也就是说,您在“main.c”中不包括“math.c”是正确的。正如 Muzol 在您的问题下方的评论中所解释的那样,编译器负责将两个目标文件链接在一起。特别是main.o 将包含信息,在您在C 源中调用add 的地方显示“图add 在哪里,并在此处使用”。同样在math.o 中,它会放置“add 在这里”的信息。 ...
  • ... 链接器获取这两条信息并进行处理,以便从math.o 中的main.oadd 的调用到达正确的位置。
  • 好的,现在说得通了。谢谢你的回答,dgnuff。
猜你喜欢
  • 2013-11-16
  • 2018-11-14
  • 2017-01-19
  • 1970-01-01
  • 2016-11-16
  • 2013-08-21
  • 1970-01-01
  • 2021-05-03
  • 1970-01-01
相关资源
最近更新 更多