今天用gcc编译器为大家演示一下C语言的编译过程
首先,我们将贴上我们朴实无华的源代码
1. 预编译过程由.c --生成–> .o文件
通过 gcc -E main.c -o main.i 执行c语言的预编译过程,生成main.o文件
让我们怀着敬畏的心情瞧一瞧生成的main.o文件是啥样子
(因为篇幅原因,上面截图只展示原文件的几十分之一的代码)
可以发现最下面是我们的源代码部分,也就是main函数,那么,main函数上面的几千行代码都是什么东西呢?
其实啊,那是我们的#include <stdio.h>, 即是我们定义的宏展开的样子
千万别小看这个文件,它可是可以直接运行的
如果有神探的话,可以发现,我上面那个main函数是有语法错误的
我的main函数是这样的
int int mian(){
printf(".....");
return 0
}
1234
聪明的你们可以得出一个什么结论呢?
在预编译过程中是不会进行语法检查的,只会单纯的将我们定义的宏进行展开
由.i文件生成.s汇编文件
gcc -s main.i -o main.s
这一步我赶紧偷偷将语法改正过来,因为有了语法检查喽(其实也是必然的,因为有语法错误怎么能编译为正确的汇编代码呢)
这个汇编文件包括我们下一步生成的目标文件是不可以直接运行的,因为它里面的函数调用等等也就是符号引用,并不知道此时他的真正的文件地址在哪里
生成目标文件gcc -c main.s -o main.o
我们采用file命令查看一下这个目标文件
发现这个文件是Mach-O类型的,什么是Mach-O呢?
虽然macos拥有着unix上的很多特性,但是并没有采用unix上可执行文件elf(excutable link format)格式, 它采用了Mach-O作为它的可执行文件的格式, 哦,所以说,它其实就是一个mac平台上的可执行文件, 类似于unix的elf和win的PE
但是呢,它还没有进行链接,例如我们main函数中引用的printf的真正内存地址它还是没有的,所以,并不是一个真正意义上的可执行文件
激动。。。终于到了最后一步了
gcc -v main.o -o main 生成我们的可执行文件
我们双击一下这个文件,就可以发现这个文件可以正常运行了,是不是非常四高一呢?