这里有几件不同的事情。首先,我将介绍多个文件的基本编译是如何工作的。
如果你有多个文件,重要的是声明和函数定义之间的区别。定义可能是您在定义函数时习惯的定义:您编写函数的内容,如
int square(int i) {
return i*i;
}
另一方面,声明允许您向编译器声明您知道函数存在,但是您不告诉编译器它是什么。例如,你可以写
int square(int i);
编译器会期望函数“square”在别处定义。
现在,如果你有两个不同的文件想要互操作(例如,假设函数“square”在add.c中定义,并且你想在main.c中调用square(10)),你需要同时做一个定义和一个声明。首先,在add.c中定义square。然后,在main.c的开头声明它。这让编译器知道它在编译main.c时有一个函数“square”,它在别处定义。现在,您需要将main.c和add.c编译为目标文件。你可以通过电话来做到这一点
gcc -c main.c
gcc -c add.c
这将生成文件main.o和add.o.它们包含已编译的函数,但不完全可执行。这里要理解的重要一点是,main.o在某种意义上是“不完整的”。在编译main.o时,你告诉它函数“square”存在,但函数“square”没有在main.o中定义。因此main.o对函数“square”有一种“悬空引用”。除非将它与另一个包含“square”定义的.o(或.so或.a)文件合并,否则它不会编译成完整的程序。如果您只是尝试将main.o链接到程序中,即
gcc -o executable main.o
您