大家对C语言的编译过程可能有个大致的理解,但是,详细到每一步具体都干了啥,可能有的人不是很清楚啦,也包括我,要不然,就不会做笔记了,哈哈...
0.主要步骤
① 步骤
编写源程序(.c) → 预处理 → 编译 → 汇编 → 链接
② 中间文件
注:GCC的目标文件(机器码)的后缀是 .o
Visual C++的目标文件的后缀是 .obj
1.预处理
① 预处理指令
大家刚开始写C语言程序时,肯定看到过这样的指令:
#include <stdio.h>
.h : 头文件扩展名,头文件包含C函数的声明与宏定义,可被多个源文件中引用共享. 有两种类型的头文件,一种是程序员编写的头文件和编译器自带的头文件,为区别这两种类型的头文件,写法略有不同,如下:
自定义头文件:#include "***.h"
库文件:#include <***.h>
在程序中使用头文件,需要使用C预处理指令#include来引用它. 前面我们已经看到过stdio.h头文件,它是编译器自带的头文件.
其实预处理指令不仅仅只有#include,如下:
② 现在我们来说一下预处理操作到底干了些什么 ?
✦ 将所有的define删除,并且展开所有的宏定义,也就是:字符替换;
✦ 处理所有的条件编译指令,#if, #ifdef, #ifudef等;
✦ 处理#include,将#include指向的头文件插入到该行;
✦ 删除所有注释;
✦ 添加行号和文件标示,这样的在调试和编译出错时才知道是哪个文件的哪一行;
✦ 保留#pragma编译指令,因为编译器需要使用它们.
2.编译
编译的过程实质是把高级语言翻译为汇编语言的过程,那到底对 .i文件 做了些什么呢?
✦ 词法分析;
✦ 语法分析;
✦ 语义分析;
✦ 优化后生成相应的汇编代码.
从 高级语言 → 汇编语言
3.汇编
其实我们经常把编译和汇编统统说成:编译.
汇编就是将汇编语言转成机器语言
汇编语言 → 机器语言 (二进制)
4.链接
链接的作用如下:
✦ 当源程序很大时,可以将它分为多个源程序,通过编译可以形成多个目标文件(Unix: .o),这时我们需要用链接器把它们连接到一起,生成一个可执行文件;
✦ 程序中调用了某个库文件中的子程序, 需要将这个库文件和该程序生成的目标文件连接到一起,生成一个可执行文件;
✦ 一个源程序编译后,得到了存有机器码的目标文件,目标文件中的有些内容还不能直接用来生成可执行文件,链接器程序将这些内容处理为最终的可执行信息. 所以,在只有一个源程序文件,而又不需要调用某个库中的子程序时,也必须用链接器对目标文件进行处理,生成可执行文件.
参考:
C语言真正的编译过程 - 无忧小菜 - 博客园
C语言编译过程详解 - CarpenterLee - 博客园
C语言的编译过程