库头文件仅包含函数的声明。那么,当我们调用库函数时,函数究竟是如何运行的呢?
Ex:int strcmp ( const char * str1, const char * str2 );
是C中strcmp函数的声明。
当我们在程序中调用strcmp函数时,如果头文件中没有函数体,strcmp函数究竟是如何执行的?
答案 0 :(得分:3)
头文件只包含函数声明。这是他们的主要目的之一,即揭示您必须使用的内容而不必担心实施
就实现的位置而言,运行时库会在构建时添加到程序中,因此作为编码器,您可以调用所有这些函数,因为您有一个函数定义的“前向”声明,但是直到运行时才加载实现。
之所以这样,是因为在每个使用它的程序中复制类似printf的实现代码是愚蠢的。这将是对内存的极大浪费!所以相反,只有声明暴露给你,程序员和操作系统在运行时共享内存中函数的实现。
答案 1 :(得分:3)
要理解程序如何使用strcmp,即使编译器只看到它的声明,也必须理解链接的过程。编译C程序包括三个步骤:
在第三步中,所谓的链接器(通常是ld
)基本上将所有链接目标文件的内容转储到可执行文件中并解析所有符号。符号是具有全局名称的任何内容,例如函数或全局变量。
当程序调用{{1}}时,编译器生成的目标文件实际上并不包含所述函数的定义。相反,只有对符号strcmp
的引用将在稍后由链接器解析。链接器检查所有目标文件以及全局库,然后解析这些引用。
答案 2 :(得分:2)
strcmp
位于运行时库中,在构建可执行文件时会将其添加到程序中。有关其工作原理的详细信息因操作系统而异。
答案 3 :(得分:2)
在这种情况下,它与任何其他用户定义的标头没有区别。
如果您没有包含相应的标题(例如string.h
的{{1}}),那么隐式声明将由编译器完成。
如果在运行时没有找到函数定义(即根据您的假设在库中丢失),那么链接器在与默认情况下完成的标准C库链接时会抱怨(例如在执行时{ {1}}如果是gcc)。
答案 4 :(得分:2)
您想要使用的代码如printf
已经编译并存储在某处。当链接器将目标代码与标准库链接时,构建最终的可执行文件。
尝试gcc -c somefile.c
,看看你得到了什么。
同时尝试gcc -v
选项并了解它提供的输出。
找出ld
命令的作用,你会得到答案。
我认为这也应该对你有帮助:All about compilation/linking/related
更新:
同样想象一下,如果您为printf
中的每个计划定义stdio.h
并且您包含stdio.h
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
将变得非常巨大。相反,最好在需要时从一个地方调用printf
stdio.h
中经常使用的函数
答案 5 :(得分:1)
它存在于已编译的库中。在链接到某个库的同时编译项目时,预编译的库将被添加到最终编译中。