我正在学习C语言并正在窥视Linux目录/usr/include
中的一些头文件,例如stdio.h
,stdlib.h
等。真正困扰我的是我看到所有函数使用extern
关键字定义,这意味着它们仅在没有任何定义的情况下声明,例如:
extern FILE *fopen (__const char *__restrict __filename,
__const char *__restrict __modes) __wur;
每个其他头文件中的每个其他函数都是如此。我的问题是,如果他们只被宣布在他们的实施的哪里?它们必须在某处实现吗?
答案 0 :(得分:8)
这些被称为函数原型。它们告诉编译器该函数存在,但不是(尚)。编译器使用它来确保你正确地调用函数,但就是这样。
编译完成后,将调用链接器。这就是魔术发生的地方。链接器确定哪个库具有该函数的实际实现。在这种情况下,它可能会出现在标准库中(在某些系统上称为libc),它会被自动拉入。链接器会执行其操作,然后您对该函数的调用将由库处理。
如果原型存在,但无法找到实现,则会出现链接器错误(类似于“未定义符号”的行)。如果缺少原型,代码将编译,但您可能会收到警告(感谢Jim Balter提供有关此信息的信息)。
答案 1 :(得分:3)
头文件只定义标准库函数的接口,而不是实现;它们(通常)不包含任何可执行代码。
这取决于编译器和平台,但通常标准库函数已经编译并收集到您的代码链接的二进制文件中以生成可执行文件。
如果您使用的是使用gcc的Linux系统,则可以在/usr/lib
下找到这些库文件。 libc.a
通常包含大量C标准库函数(stdio,stdlib,string等)。数学函数分别存储在libm.a
中。在正常情况下,gcc会自动链接/usr/lib/libc.a
,因此您无需担心。如果需要使用数学库函数,则需要在命令行中添加-lm
以链接数学库。
请注意,大多数实现都不提供库函数本身的源代码;你得到的只是预编译的二进制文件。
答案 2 :(得分:1)
.h
个文件包含声明,定义在某个目标文件中的某处。可以找到更多信息here。