你如何链接同名的.c和.h文件?

时间:2009-06-06 21:17:12

标签: c

在阅读库源代码时,我发现有.c.h个同名文件。在主源中,包含.h文件,但不包括.c文件。当我查看.h文件中的代码时,它也不会#include同名的.c文件。我错过了什么吗?当同名的.c文件为.h时,编译器是否自动包含#include文件?

7 个答案:

答案 0 :(得分:8)

典型的.h文件用作.c文件的“目录”,包括函数原型,typedef等。程序包括.h,以便他们了解功能和类型。

.c文件是单独编译的,并生成包含实际代码的目标文件(.o.obj)。

然后,通过Makefile,Project文件或类似方法将目标文件绑定到主程序。然后,目标文件与主程序链接,产生一个功能整体。

对于库, 没有主程序。目标文件收集在一起并以特殊格式(对于静态或动态库)。使用该库的任何程序都将包含上述.h,并链接到库。

答案 1 :(得分:8)

没有魔力。编译C程序时,有两个主要步骤。

首先,编译的每个编译单元都是隔离的。 (编译单元基本上是一个.c文件,加上它包含的所有内容)。

在这个阶段,它对其他.c文件中包含的内容一无所知,这意味着它无法生成完整的程序。它能做的是生成一些带有“填空”点的代码。如果从foo.c调用一个在bar.h中声明并在bar.c中定义的函数,则编译器只能看到函数存在。它在bar.h中声明,因此我们必须假设完整定义存在 somewher 。但由于该定义位于另一个编译单元内,我们还不能看到它。因此,编译器会生成调用该函数的代码,并在其上注明“在实际知道后填写此函数的地址”。

一旦每个编译单元都以这种方式编译,你就会留下一堆目标文件(如果你用GCC编译,通常是.o,如果你使用MSVC则是.obj),包含这种“填空” “代码。

现在链接器获取所有这些目标文件,并尝试将它们合并在一起,这样就可以填充空白。现在可以找到我们为上面生成调用的函数,因此我们可以将其地址插入到调用中。

因此,如果.c文件与.h具有相同的名称,则不会发生任何特殊情况。这只是一个让人类更容易弄清楚每个文件中的内容的惯例。

编译器不关心。它只需要每个.c文件,以及它包含的任何内容,并将其编译为目标文件。然后链接器将所有这些目标文件合并为一个可执行文件。

答案 2 :(得分:6)

没有。不需要在.h文件中包含.c文件。 .h文件通常不直接作为编译器输入传递,但其唯一目的是包含在其他文件中。

通常,它类似于:

"a.c"    includes   "a.h"
"b.c"    includes   "c.h"

编译“a.c”和“b.c”并链接输出文件。

答案 3 :(得分:4)

.h文件包含.c文件中函数的声明。想要使用另一个.c文件的功能的其他.c文件需要这些声明。因此.c文件永远不会包含.c文件。

将每个.c文件编译成目标文件,然后将所有这些目标文件链接到库或应用程序中。

答案 4 :(得分:1)

预处理器没有做任何神奇的事情。

要在包含的目录中包含某些内容(难以使用您自己的标题)

#include <foo.h>

或在同一编译目录中包含某些内容

#include "foo.h"

所有这一切都需要foo.h的文本并将其直接插入输出。 gcc a.c -E将打印出预处理后的样子。

这是一个'愚蠢'的过程,因为编写自己的程序将正确处理#include是一种微不足道的练习。

答案 5 :(得分:1)

你的问题有点用词不当。您针对* .h文件进行编译,并且忽略内联,您将链接到* .c文件。

如果你回到基础,你可以说:

  • “.h”文件是您的库的接口,即您必须编译的内容和
  • 匹配* .c文件是您希望该函数执行的操作。

所以,举个例子:

  1. 一个文件add_integers.h只是声明了一个函数,比如addInts(),它接受两个整数并返回一个整数,它是两者的总和,并且
  2. 文件add_integers.c(pp)提供函数addInts()的实现,该函数使用一个算法,该算法采用两个整数,将它们相加并返回结果。
  3. addInts()函数的实现者可以自由地修改实现addInts()函数的软件。

    根本没有修改addInts()函数的接口(即根本不修改addInts.h),然后可以免费分发包含addInts函数的修改实现的新共享库。人们不得不重新编译新的addInts库版本。

    哇!为什么阅读这个解释听起来像Danny Kaye和“The Vessel with the Pessel”?

    您可能希望了解Bertrand Meyer与Eiffel合作的作品以及“Design by Contract”。

答案 6 :(得分:0)

如果我想用C或C ++创建一个静态库,我会把我的函数原型放在.h中,将实际的函数代码放在.c或.cpp中。之后我编译了我的.cpp来制作一个.lib

要将我的.h链接到我的.lib,我在.h

中编写了这个预处理器命令
#pragma comment (lib, "theNameOfTheLibFile.lib")

之后如果我在程序中包含.h,我的程序就知道在哪里可以找到匹配的库。