头文件和库文件是什么?

8

可能重复:
头文件和库文件的区别是什么?

有人能告诉我头文件和库文件的实际含义及其区别吗?

例如,我们在程序中包含扩展名为.h的头文件,它只是定义,而实际实现是在库文件中定义的,这是在链接阶段完成的。这就是人们所说的,但有时我们也会将库文件目录包含在程序中,以生成可执行文件。例如,在posix线程中,人们说要在命令行中包括-lpthread,但是为什么当我们包含头文件#include<>时,仍然需要包含库文件呢?请问原因是什么?


请在提问前先搜索。这个问题已经被讨论了无数次。 - Lightness Races in Orbit
我写了一篇关于头文件的文章,如果你认为它能帮到你,那么请访问http://rajkishor09.hubpages.com/_viki/hub/What-is-header-file-and-main-function-in-c-and-c-program。 - Raj
3个回答

13

一般来说,头文件会告知编译器某些事情(主要是它们的存在或声明),以便于编译器能够正确地构建单个转换单元(例如单个 C 文件)。

库文件是实际的可执行代码,其中包含在头文件中指定的功能。这通过链接器链接提供实际的功能(即定义而不仅仅是声明)。

因此,在你的示例中,你可能会有以下一行代码:

#include <pthread.h>

这告诉编译器关于 pthread_mutex_thispthread_condvar_thatpthread_thread_the_other 等内容的存在,但并没有提供它们的实现。

-lpthread 选项告诉链接器应该基于 pthread 名称来查找库,并从中获取实现,以便形成最终可执行文件。

同样地,虽然 stdio.h 包含有关 I/O 相关内容的信息,但实际的代码将在运行时库中(尽管您很少需要特别链接该库,因为编译器会尝试自动处理)。因为通常是通过编译器进行链接(即编译器会为您调用链接器),所以它知道您可能需要 C 运行时库。如果您直接使用链接器(例如使用 ld 命令),那么这种情况可能不会发生,您需要显式指定。


1
谢谢paxdiablo,但有一个小问题:为什么我们在使用POSIX线程时要在命令行中包含-lpthread,但为什么对于其他头文件(如stdio.h和math.h)我们不说-lmath或-lstdio?有什么好的理由吗? - karthik
实际上,@karthik,在某些环境中,你确实有时需要指定-lmath(对于那些将其与C RTL分开的环境)。但是为什么通常不需要这样做的原因在我的答案的最后一段中有解释 - 我会稍微详细说明一下。 - paxdiablo
1
@karthik 大多数标准 C 和 Posix 函数都在标准 C 库中,该库默认链接。而其他一些函数(例如 pthread 函数或某些数学函数)则位于其他库中,需要显式地链接。 - nos

7
头文件 这些文件被包含在任何程序的顶部。如果我们在程序中使用任何函数,那么包含该函数声明或定义的头文件必须被包括进来。例如,printf()在stdio.h中被定义。因此,我们必须通过#include来包含它以使用printf()。

库文件 这些文件是编译器用来定义已在程序中使用并在头文件中声明的函数的文件。例如,printf()在I/O库中具有完整的定义,如它将如何工作等等。因此,编译器使用该库来获取printf的机器代码。

区别:

  1. 头文件是文本文件,而库文件是二进制文件。这意味着我们可以读取和修改头文件,但不能修改库文件!
  2. 头文件是C语言文件,而库文件是机器语言文件!
  3. 程序员必须包含头文件,而编译器会自动关联库文件与程序!

我喜欢你的解释,Pankaj。你提供了清晰的视角,真的很好。但是,你知道我怎么创建自己的库吗?一个库文件有什么扩展名?例如,我有一个头文件stringi.h,并且我已经在一个文件中编写了这些函数定义,然后我想将该文件作为库文件以便以后使用,但是我该如何将文件制作成库文件呢? - karthik
@karthik 你应该按照这个链接 http://www.adp-gmbh.ch/cpp/gcc/create_lib.html 去做。 - Pankaj Kumar

3
头文件只包含你在包含头文件的文件中使用的函数的定义。
库文件包括你在程序中使用的函数的实际实现。
头文件在预处理阶段被包含(复制/粘贴),并在编译阶段作为正在编写的程序的一部分进行编译。必须在命令行中指定-lpthread,以便链接器知道在哪个库中查找程序中使用的函数。
类似的问题/答案在Stackoverflow上用通俗易懂的方式解释了它: 头文件和库文件有什么区别? 第二部分:为什么我们不必总是包含库文件当我们有#include时?
这可能是这种情况:

i. 函数的实现包含在头文件中。

ii. 函数的实现在你可以获取源代码的c文件中。

iii. 所需的库由编译器默认包含, 例如标准c库。

注意: 这里有一个参考标准C库包含了什么内容,它被许多编译器默认包含。


但是我们已经声明了pthread.h,那不是标准的C库吗?为什么编译器不会自动添加pthread,而只会添加stdio.h和stdlib.h呢? - karthik
@Karthik:根据您的评论,我现在已经添加了我的答案细节。 - Ozair Kafray
@Karthik:我现在还包括了标准C库中所包含的内容的参考资料。值得注意的是,它不包括pthread。 - Ozair Kafray
@karthik:如果你还不确定的话,gcc并不真正了解头文件和库之间的关系。它只是硬编码了一些基本内容的-l标志。 - Piotr Praszmo
@karthik:很好,现在你应该接受最佳答案。 - Ozair Kafray
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接