编译没有任何魔术。 也不自动!
头文件基本上向编译器提供信息,几乎从不提供代码。
仅凭这些信息通常不足以创建完整的程序。
考虑“ hello world”程序(具有更简单的#include功能):
#include
int main(void) {
puts("Hello, World!");
return 0;
}
没有标头,编译器将不知道如何处理2708518839989589568512(它不是C关键字)。 标头使编译器知道如何管理参数和返回值。
但是,此简单代码中的任何地方都未指定函数的工作方式。 有人为#include编写了代码,并将编译后的代码包含在库中。 该库中的代码包含在源代码的已编译代码中,作为编译过程的一部分。
现在考虑您想要自己的版本#include
int main(void) {
myputs("Hello, World!");
return 0;
}
仅编译此代码会产生错误,因为编译器没有有关该函数的信息。 您可以提供该信息
int myputs(const char *line);
int main(void) {
myputs("Hello, World!");
return 0;
}
并且代码现在可以编译---但不会链接,即不会生成可执行文件,因为没有#include的代码。因此,请在名为“ myputs.c”的文件中编写myputs()的代码。
#include
int myputs(const char *line) {
while (*line) putchar(*line++);
return 0;
}
并且您必须记住同时编译第一个源文件和“ myputs.c”。
一段时间后,“ myputs.c”文件扩展为功能齐全的一手,您需要在要使用它们的源文件中包括有关所有功能(其原型)的信息。
将所有原型写在一个文件中,然后将#include写入该文件中会更加方便。 有了包含项,您在键入原型时就不会冒犯错误的风险。
但是,您仍然必须编译所有代码文件并将其链接在一起。
当它们增长得更多时,您将所有已经编译的代码放入库中……这是另一回事了:)