1、预处理编程
预处理指令的执行主要包含下列事情:函数
1.头文件的包含优化
2.注释的删除操作系统
3.宏定义的替换翻译
4.条件编译的选择编译器
指令:gcc -E test.c -o test.i it
/* 调用的是预处理器cpp, -E:只进行预处理操做,-o:输出到<文件> , .i表示产生的临时文件 Intermediate */编译
2、编译table
编译以前,C语言编译器会进行词法分析、语法分析(-fsyntax-only)。test
在确认全部的指令都符合语法规则以后,将其翻译成相应的后缀为S的汇编文件。
指令:gcc -S test.i -o test.S
/* 调用的是编译器ccl, -S:编译到汇编语言,不进行汇编和连接, .S:表示汇编文件,注意于.s汇编文件的区别 */
.s :汇编语言源程序;汇编
.S:汇编语言源程序;预处理,汇编
小写的s文件,在后期阶段不在进行预处理操做,因此咱们不能在这里面写预处理的语句在里面
大写的S文件,还会进行预处理、汇编等操做,因此咱们能够在这里面加入预处理的命
3、汇编
在编译与汇编之间,编译器一般还会作一些优化操做。
汇编过程实际上指把汇编语言代码翻译成目标机器指令的过程
指令:gcc -c test.S -o test.o
/* 调用的是汇编器as,-c:编译、汇编到目标代码,不进行连接, .o表示产生目标文件, object
此时用file查看test.o文件的类型为ELF 32-bit LSB relocatable类型,这是可重定位的格式 */
4、连接
由汇编程序生成的目标文件并不能当即就被执行,其中可能还有许多没有解决的问题。例如,某个源文件中的函数可能引用了另外一个 源文件中定义的某个符号(如变量或者函数调用等);在程序中可能调用了某个库文件中的函数等等。全部的这些问题,都须要经连接程序的处理方能得以解决。
连接程序的主要工做就是将有关的目标文件彼此相链接,也即将在一个文件中引用的符号同该符号在另一个文件中的定义链接起来,使得全部的这些目标文件成为一个可以诶操做系统装入执行的统一总体。
函数库通常分为静态库和动态库两种。静态库是指编译连接时,把库文件的代码所有加入到可执行文件中,所以生成的文件比较大,但在运行时也就再也不须要库文件了。其后缀名通常为”.a”。动态库与之相反,在编译连接时并无把库文件的代码加入到可执行文件中,而是在程序执行时由运行时连接文件加载库,这样能够节省系统的开销。动态库通常后缀名为”.so”,如前面所述的libc.so.6就是动态库。gcc在编译时默认使用动态库。
指令:gcc test.o -o test
/* 用file查看test文件类型为:ELF 32-bit LSB executable,这是能够被执行的文件格式 */