C语言中的头文件及其用法

3

库的头文件只包含函数的声明。那么,当我们调用库函数时,函数是如何运行的呢?

例如:在 C 语言中,int strcmp ( const char * str1, const char * str2 ); 是 strcmp 函数的声明。

当我们在程序中调用 strcmp 函数时,如果函数体不在头文件中,那么 strcmp 函数是如何执行的呢?


1
程序需要编译和链接才能运行。库函数的代码在某个库中。 - Carl Norum
6个回答

3
头文件仅包含函数声明。这是它们的主要目的之一,它们可以在不担心实现的情况下公开您需要处理的内容。

至于实现的位置,在构建时会添加运行时库到您的程序中,因此作为一个编码人员,您可以调用所有这些函数,因为您有它们的函数定义的“前向”声明,但是直到运行时才加载实现。

这样做的原因是因为在每个使用它的程序中复制printf等东西的实现代码是很愚蠢的。这将浪费大量内存!因此,只有声明暴露给您,程序员,操作系统在运行时在内存中共享函数的实现。


糟糕!谢谢!不过如果你愿意,可以在头部添加更多内容。 - 75inchpianist
发现了一篇对我们俩都很有帮助的好文章 :D http://www.umich.edu/~eecs381/handouts/CHeaderFileGuidelines.pdf - Deepankar Bajpeyi

3
了解如何使用strcmp函数的程序是如何工作的,即使编译器只看到它的声明,也必须了解链接的过程。C程序的编译包括三个步骤:
1.预处理(将所有包含的头文件转储到源代码中)
2.编译(从源代码生成对象文件)
3.链接(将多个对象文件链接在一起)
第三个步骤中,所谓的“链接器”(通常为ld)基本上将所有链接的对象文件的内容转储到可执行文件中,并解析所有符号。符号是具有全局名称的任何内容,例如函数或全局变量。
当您的程序调用strcmp函数时,由编译器生成的对象文件实际上不包含该函数的定义。相反,只有一个对将由链接器稍后解决的符号strcmp的引用。链接器检查所有对象文件以及全局库,然后解析这些引用。

2
您想使用类似于printf的代码已经被编译并存储在某个地方。当链接器将您的目标代码与标准库链接时,将构建最终可执行文件。
尝试使用gcc -c somefile.c命令并查看结果。
还可以尝试使用gcc -v选项并了解其输出内容。
找出ld命令的作用,您就能得到答案。
此外,我认为以下内容应该对您有所帮助:有关编译/链接/相关的所有信息 更新:
此外,想象一下,如果您为每个包含stdio.h的程序定义了printf,会怎样呢? program.c
#include <stdio.h>  //suppose this contains definition of printf     

int main()
{            

/*Call printf()  somewhere or maybe not */

}

gcc program.c -o output

这里所有在 stdio.h 中定义的内容都将在 program.c 文件中被替换,使得你的可执行文件 output 变得非常巨大。相反,更好的做法是在需要时从一个地方调用经常使用的函数,比如 stdio.h 中的 printf


2

strcmp是运行库中的函数,在构建可执行文件时会被添加到程序中。这个过程在不同操作系统上的细节有所不同。


2
在这种情况下,它与任何其他用户定义的头文件没有区别。如果您不包括相应的头文件(例如strcmpstring.h),则编译器会进行隐式声明。如果在运行时找不到函数定义(即根据您的假设在库中缺少),则链接器将在默认情况下与标准C库进行链接时发出警告(例如,在使用gcc时进行-lc)。请注意保留HTML标记。

问题并未询问缺少声明或声明的目的,因此此答案中的前两段是无关的。第三段提到了找不到函数定义,但问题也没有询问未找到函数。它询问相反的情况,即如何找到函数。这个“答案”并没有回答关于如何在程序中执行strcmp而其定义显然没有出现的问题。虽然它(终于)提到了C库,但它并没有解释链接对象模块。 - Eric Postpischil
@EricPostpischil 当我们在程序中调用strcmp函数时,如果函数体不在头文件中,那么strcmp函数会如何执行呢?虽然函数体通常不在头文件中,但问题很明确:如果函数定义丢失了怎么办?或者这就是我的理解。 - P.P
不,问题本质上是“即使在头文件中没有函数定义,它为什么不会丢失?”如果问题是您所建议的那样,那么提问者将报告链接器错误消息并询问为什么会出现这些错误。他们并没有询问意外缺少定义的问题,而是询问意外存在定义的问题。 - Eric Postpischil
这就是我说的。如果链接器找不到,它会抱怨。没有给出代码,只有一个strcmp的示例案例。你提出的关于如果函数定义不在头文件中如何找到的建议似乎是一个有效的论点,但我不能确定这是否是OP真正想问的。 - P.P

1

它存在于编译好的库中。当您在链接到某个库时编译项目时,预编译的库将添加到最终编译中。


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