编译过程为扫描程序–>语法分析–>语义分析–>源代码优化–>代码生成器–>目标代码优化;
语法分析的结果为分析树parse tree或者语法树syntax tree
C程序运行需要的过程:预处理、编译、汇编、链接
以mytest.c程序为例讲解:
一、预处理(-E)
将mytest.c文件进行预处理,-E就是进行预处理,-o是将预处理后的文件存储在mytest.i文件中,mytest.i文件叫做目的文件
gcc -E mytest.c -o mytest.i
预处理实现的工作:头文件展开、去注释、条件编译、宏替换
(1)头文件展开:通过编译器找到指定的头文件,并将头文件对应的内容拷贝至源文件
(2)去注释 ,打开mytest.i文件(右边)中,可以看到mytest.c文件中注释的代码没有显示出来
(3)宏替换,在mytest.i文件中宏替换成了它所代表的内容
(4)条件编译,满足条件的才会在mytest.i文件中编译出来,mytest.c中OS为0,则满足条件的mytest.i文件中打印相应满足的内容
二、编译(-S)
编译:C代码编译成为汇编,-S就是在编译这就停止,不再继续向下汇编等工作
编译阶段的编译优化:
(1)死代码删除是编译最优化技术,指的是移除对程序运行结果没有影响的代码,死代码是指永远不会执行到的代码,不是注释,比如if(0){…},大括号里的就是死代码。
(2)函数内联可以避免函数调用中压栈和退栈的开销
(3)For循环的循环控制变量通常很适合调度到寄存器访问
(4)强度削弱是指执行时间较短的指令等价的替代执行时间较长的指令
gcc -S mytest.i -o mytest.s
mytest.s文件内容为汇编程序:
三、汇编(-c)
汇编:将汇编语言翻译成目标文件(可重定向目标文件),是一个二进制文件(不可执行,还没完成最后一步的链接)
gcc -c mytest.s -o mytest.o
mytest.o文件是乱码
四、链接
- 链接:目标文件,只有函数的调用,没有函数的实现
- 链接过程的本质是将自己的调用过程和具体的实现过程关联起来
gcc mytest.o -o mytest
ldd mytest:查看所执行程序mytest所依赖的库