gcc编译器
一、gcc的工作流程
gcc编译器将c源文件到生成一个可执行程序,中间一共经历了四个步骤:
四个步骤并不是gcc独立完成的,而是在内部调用了其他工具,从而完成了整个工作流程, 其中编译最耗时, 因为要逐行检查语法。
- 下面以 test.c 为例介绍 gcc 的四个步骤:
gcc -E test.c -o test.i
gcc -S test.i -o test.s
gcc -c test.s -o test.o
gcc test.o -o test
一步生成最终的可执行程序:
gcc test.c -o test
二、gcc 常用参数
-
-v 查看gcc版本号, --version也可以
-
-E
生成预处理文件 -
-S
生成汇编文件 -
-c
只编译, 生成.o文件, 通常称为目标文件 -
-I
指定头文件所在的路径 -
-L
指定库文件所在的路径 -
-l
指定库的名字扫描二维码关注公众号,回复: 14097538 查看本文章 -
-o
指定生成的目标文件的名字 -
-g
包含调试信息, 使用gdb调试需要添加-g参数 -
-On n=0∼3
编译优化,n越大优化得越多
三、gcc编译测试
-
1、创建一个.c文件:
vim hello.c
-
2、
gcc -E hello.c -o hello.i
-----通过预处理器使头文件展开,宏替换、注释去掉
-
3、
gcc -S hello.i -o hello.s
-----通过编译器使C文件变为汇编文件
-
4、
gcc -c hello.s -o hello.o
-----通过汇编器将汇编文件变为二进制文件
-
5、
gcc hello.o -o hello
-----通过链接器将函数中相应的代码组合到目标文件中
-
6、
./hello
-----执行
总结
通过学习了解gcc编译的过程,我们将一个程序运行到结束的完整过程进行简单的叙述:
1、预编译
预编译主要处理的是带#号的预编译指令,通过预处理器将注释去掉,文件展开,宏替换:
① 删除所有的#define,展开所有宏定义。
② 删除所有注释,//和/* */。
③ 处理所有条件预处理指令,如"#if"、"#endif"、"#ifdef"、“elif”、"#else"
④ 处理#include预编译指令,将文件内容替换到它的位置,此过程递归进行。
⑤ 保留所有#pragma编译器指令,编译器需要用到它们,如:#pragma once是为了防止文件被重复引用。
⑥ 添加行号和文件标识,便于编译时产生调试用的行号信息,即当编译出错或警告时能显示行号。
2、编译
将预编译得到的.i或.ii文件通过编译器ccl进行一系列词义分析、语义分析、语法分析、优化生成.s的汇编代码文件。
3、汇编
将编译得到的汇编代码文件转变为机器可以执行的指令(机器码文件),经过汇编产生的目标文件,在windows下为.obj,在linux下为.o。此过程由汇编器as完成。
4、链接
&emspl 将不同的源文件产生的目标文件进行链接,生成一个可执行程序。
补充:
链接分为静态链接和动态链接:
静态链接:
将函数和数据被编译进一个二进制文件,也就是将所有程序模块都链接成一个单独的可执行文件。
优点:运行速度快。
缺点:会造成空间浪费,因为每个可执行程序中对所有需要的目标文件都要一份副本,如果多个程序对同一个目标文件依赖,就会产生多个相同的副本。
动态链接:
将程序按照模块拆分成各个相对独立部分,在程序运行时才将它们链接在一起形成一个完整的程序。
优点:共享库、更新方便。
缺点:运行时,性能不如静态链接,因为它每次执行都需要链接。
期待大家和我交流,留言或者私信,一起学习,一起进步!