对C语言的了解非常薄弱,想知道为什么在一个.c文件当中可以使用另外一个.c文件定以的函数,为了帮助问题的阐述,接下来用简单的代码复现一下我们的问题。
a.c文件:
#include<stdio.h>
void hello(){
printf("hello world!")
}
然后在b.c文件当中调用hello()这个函数,b.c文件:
void hello();
int main(void) {
hello();
//输出:hello world!
}
因为我对C语言的了解十分的少,仅限于刚上大学那会的CFree写了一点,所以对这个背后它们到底怎么来做到的十分好奇。
先说结论,再实验
可能因为现代的IDE太发达了,写好代码点一下运行按钮就结果出现在屏幕上,以致于都不知道背后发生了什么,不知道C语言编译的整个流程。
结论
点击运行按钮后,编译器会将当前项目中所有的.c文件经过编译以后,再由链接器(连接器是编译器中的一个部分)将所有的.o(linux平台下)或者.obj(windows平台下)链接为一个可执行文件,比如说windows下的.exe,linux下的.elf文件。
实验部分
文件就是上面两个最简单的文件a.c和b.c,我们要在b.c中调用a.c中的函数。前面结论说了,整个是连接器做的工作,所以我们就先将代码编译为.o文件,但是不链接。
我用的编译器是gcc(ubuntu系统),gcc可以通过一些选项编译好.o文件,先输入命令gcc --help查看下这些选项
要使用的就是** gcc -c filename**整个命令。
接下来我们对上面的两个文件先编译为.o文件,稍微再说下,什么是.o文件呢?
.o文件(object file):
.o文件里面包含的基本是c语言经过汇编后的机器码了,还有一些符号,这些符号是给链接器使用的(linker,再linux平台下输入ld命令就是使用连接器来链接.o文件)。连接器在链接的时候将本项目中的所有.o文件链接在一起就成为了一个可执行文件了(比如说.exe文件)
回归正题,我们将上面两个文件编译为.o文件:
gcc -c a.c
gcc -c b.c
不出意外的话,在桌面上就有两个.o文件了,我这里截张图示例
此时两个.o文件还没有经过链接,因此如果直接根据b.o这个来生成可执行文件那么将会报错,错误如下所示:
报错
显示说hello这个引用未定义,所以我们将两者链接起来再运行 结果
可以看到通过将两个.o文件连接起来后,就可以正常运行了。
网友评论