初学编程一般都使用封装好的集成开发环境(IDE),而IDE是怎么工作的呢?
编译(build)
当我们使用IDE输入代码,点击编译(build)后实际上是执行了四个部分:预处理,编译,汇编,链接
图画的有点丑。。
预编译(预处理器)
- 处理所有的注释,以空格代替
- 将所有的#define删除,并且展开所有的宏定义
- 处理条件编译指令#if,#ifdef,#elif,#else,#endif
- 处理#include,展开被包含的文件(将展开的文件复制到当前文件)
- 保留编译器需要使用的#pragma指令
预处理命令:
gcc -E file.c -o file.i
编译(编译器)
- 对于处理文件进行一系列词法分析,语法分析和语义分析
- 词法分析主要分析关键字,标示符,立即数等是否合法
- 词法分析主要分析表达式是否遵循语法规则
- 语义分析在语法分析的基础上进一步分析表达式是否合法
- 分析结束后进行代码优化生成相应的汇编代码文件
编译指令
gcc -S file.c -o hello.S
汇编(汇编器)
- 汇编器将汇编代码转变为机器可以执行的指令
- 每个汇编语句几乎都对应一条机器指令
汇编指令
gcc -c file.S -o file.o
链接(链接器)
- 链接器的主要作用就是把各个模块之间相互引用的部分处理好,使得各个模块之间能够正确的衔接。
- 链接又分动态链接和静态链接,这两种方式各有优势,动态链接速度快而静态链接速度虽然没有动态快但是相比而言更加的节省内存空间,我们IDE一般使用的是静态链接。
- 静态链接库中不能再包含其他的动态链接库或者静态库,而在动态链接库中还可以再包含其他的动态或静态链接库。
- 静态链接
当执行静态链接是,链接器只是单纯的将各个库(lib)糅合到一个目标程序中中,这样的缺点是当同一份程序同时多开,在内存中每个模块都有多份,浪费了内存空间,但是如果在没有依赖库的平台上可以直接使用。- 动态链接
当执行动态链接时,链接器并不是将所有的库链接到一个文件,只是将调用的函数所在文件模块(DLL)和调用函数在文件中的位置等信息链接进目标程序
程序运行时先从内存中查看是否有该模块的拷贝,如果有则使用这个拷贝,如果没有则需要重新加载一次,多开时各个程序使用同一个库。这样的缺点就是每次执行程序时都要去查询加载,浪费时间但是节省了内存。
运行
之后再点击运行(run)后就可以看到我们的程序跑起来了
小结
- 编译器将编译工作主要分为预处理,编译和汇编三部分
- 链接器的工作是把各个独立模块链接为可执行程序
- 静态链接在编译期完成,动态链接在运行期完成
如果博客内容有错误,或者有改进的地方请多多指教。