gcc 编译过程
gcc 编译过程
从 hello.c 到 hello(或 a.out)文件, 必须历经 hello.i、 hello.s、 hello.o,最后才得到 hello(或
a.out)文件,分别对应着预处理、编译、汇编和链接 4 个步骤,整个过程如图 10.5 所示。

这 4 步大致的工作内容如下:
(1) 预处理, C 编译器对各种预处理命令进行处理,包括头文件包含、宏定义的扩
展、条件编译的选择等;
(2) 编译,将预处理得到的源代码文件,进行“翻译转换”,产生出机器语言的目标
程序,得到机器语言的汇编文件;
(3) 汇编,将汇编代码翻译成了机器码,但是还不可以运行;
(4) 链接,处理可重定位文件,把各种符号引用和符号定义转换成为可执行文件中
的合适信息,通常是虚拟地址。
下面根据 hello.c 这个示例,跟踪一下其中的细节。
(1)预处理
在 gcc 命令加上-E 参数,可以得到预处理文件。输入下列命令:
vmuser@Linux-host:hello$ gcc -E hello.c –o hello.i
将会产生 hello.i 文件,这就是 hello.c 经过预处理后的文件。实际操作结果见图 10.6。

图 10.6 预编译得到 hello.i 文件
一个原本连同空行才 8 行的代码,经过预处理,得到了一个 800 多行的预处理文件,文
件开的内容如图 10.7 所示。
图 10.7 hello.i 文件开头
hello.i 文件末尾处的内容如图 10.8 所示。

图 10.8 hello.i 文件末尾
其余部分内容请用 Vi 打开后进行查看。可以看到, hello.c 经过预处理后得到的 hello.i
文件,除了原本的几行代码之外,还包含了很多额外的变量、函数等等,这些都是预处理器
处理的结果。
(2)编译
在 gcc 编译参数加上-S,可以将 hello.i 编译成 hello.s 文件。命令如下:
vmuser@Linux-host:hello$ gcc -S hello.i
实际操作和结果如图 10.9 所示。
图 10.9 编译得到 hello.s 文件
hello.s 是一个汇编文件,可用 Vi 编辑器打开查看,如图 10.10 所示。

图 10.10 hello.s 文件内容
可以看到,该文件内容都是汇编语句。这里不对汇编进行解释。
(3)汇编
得到了汇编文件后,通过 gcc 就可以得到机器码了。在终端输入下列命令,可以得到
hello.o 文件。
vmuser@Linux-host:hello$ gcc -c hello.s
实际操作和结果如图 10.11 所示。

图 10.11 汇编得到 hello.o 文件
(4)链接
尽管已经得到了机器码,但这个文件却还是不可以运行的,必须要经过链接才能运行。
在终端输入下列命令,将会得到可执行文件 a.out。
vmuser@Linux-host:hello$ gcc hello.o
操作和结果如图 10.12 所示。

图 10.12 链接得到 a.out 文件
a.out 是 gcc 默认输出文件名称,可以通过-o 参数指定新的文件名。例如加上“-o hello”
参数,将会生成 hello 文件,这个文件和 a.out 实际上是一样的,用 md5sum 命令计算文件校
验值,两者完全一样,如图 10.13 所示。

图 10.13 a.out 和 hello 文件
链接可分为动态链接和静态链接:
动态链接使用动态链接库进行链接,生成的程序在执行的时候需要加载所需的动态
库才能运行。动态链接生成的程序小巧,但是必须依赖动态库,否则无法执行。
Linux 下的动态链接库实际是共享目标文件(shared object),一般是.so 文件,
作用类似于 Windows 下的.dll 文件。
静态链接使用静态库进行链接,生成的程序包含程序运行所需要的全部库,可以直
接运行,不过体积较大。
Linux 下静态库是汇编产生的.o 文件的集合,一般以.a 文件形式出现。
gcc 默认是动态链接,加上-static 参数则采用静态链接。再来看 hello.c 示例,在链接的
时候加上-static 参数:
vmuser@Linux-host:hello$ gcc hello.o -static -o hello_static
操作命令和结果如图 10.14 所示,可以看到,动态链接生成的文件大小是 7155 字节,
而静态链接生成的文件却有 616096 字节,体积明显大了很多。

图 10.14 静态链接和动态链接结果对比
gcc 编译过程的更多相关文章
- Linux学习---GCC编译过程
(一)GCC编译过程 预处理 cpp -o a.i a.c //生成预处理文件 等同于[gcc -E] //预处理为将宏定义(#define)等进行替换. 编译 /user/lib/gcc/i ...
- GCC编译过程与动态链接库和静态链接库
1. 库的介绍 库是写好的现有的,成熟的,可以复用的代码.现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常. 本质上来说库是一种可执行代码的二进制形式,可 ...
- 1.GCC编译过程
一. GCC编译过程 gcc -E hello.c -o hello.i // 预处理.将代码中包含的头文件和宏进行替换 gcc -S hello.i -o hello.s // 汇编.将当前文本转换 ...
- unix gcc编译过程
gcc编译过程 现代编译器常见的编译过程: 源文件-->预处理-->编译/优化-->汇编-->链接-->可执行文件 对于gcc而言: 第一步 预处理 命令: ...
- GCC编译过程
以下是C程序一般的编译过程: gcc的编译流程分为四个步骤,分别为:· 预处理(Pre-Processing) 对C语言进行预处理,生成*.i文件.· 编译(Compiling) 将上一步生成的*.i ...
- Linux系统GCC常用命令和GCC编译过程描述
前言: GCC 原名为 GNU C 语言编译器(GNU C Compiler),因为它原本只能处理 C语言.GCC 很快地扩展,变得可处理 C++.后来又 扩展能够支持更多编程语言,如Fortran. ...
- gcc编译过程简述
在linux系统上,从源文件到目标文件的转化是由编译器完成的.以hello.c程序的编译为例,如下: dfcao@linux: gcc -o hello hello.c 在这里,gcc编译器读取源文件 ...
- system 系统调用、gcc编译过程
system 库函数的功能是执行操作系统的命令或者运行指定的程序 #include <stdio.h> #include <stdlib.h>//引入库 int main() ...
- 和菜鸟一起学c之gcc编译过程及其常用编译选项【转】
转自:http://blog.csdn.net/eastmoon502136/article/details/8162626 版权声明:本文为博主东月之神原创文章,未经博主允许不得转载. 上篇文章,知 ...
随机推荐
- c++产生验证码字符串
// // Created by lk on 18-10-14. // #include <iostream> #include <cstdlib> #include < ...
- 【转】Pandas学习笔记(七)plot画图
Pandas学习笔记系列: Pandas学习笔记(一)基本介绍 Pandas学习笔记(二)选择数据 Pandas学习笔记(三)修改&添加值 Pandas学习笔记(四)处理丢失值 Pandas学 ...
- 2. 代理模式(C++)
1.介绍 代理模式:为其他对象提供一种代理以控制对这个对象的访问.这样实现了业务和核心功能分离. 在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口.在某些情况下,一个对象不适合或者不能 ...
- vue-cli3.0结合lib-flexible、px2rem实现移动端适配,完美解决第三方ui库样式变小问题
公司最近做的一个移动端项目从搭框架到前端开发由我独立完成,以前做移动端适配用的媒体查询,这次想用点别的适配方案,然后就采用了vue-cli3.0结合lib-flexible.px2rem实现移动端适配 ...
- Redash - 安装和初试
前言 当业务成长到一定规模之后,会有许多想看各种不同类型报表的需求,如果单独做在后台,那么无疑会浪费前端和后端开发的时间.所以一直都有在寻找一款好用的BI工具.后面查了一下,市面上好用的一些非商业的B ...
- Code Chef May Challenge 2019题解
传送门 \(REDONE\) 贡献可以拆成\(X(Y+1)+Y\),那么一个数\(x\)的贡献对最终答案的贡献就是\(x(a_1+1)(a_2+1)...\),那么最终答案肯定是\(\sum\limi ...
- 每天一道Rust-LeetCode(2019-06-01)
每天一道Rust-LeetCode(2019-06-01) 坚持每天一道题,刷题学习Rust. 题目描述 给出两个 非空 的链表用来表示两个非负的整数.其中,它们各自的位数是按照 逆序 的方式存储的, ...
- CSRF跨域伪造请求
后端生成一个加密token,将其设置在cookie当中,专用于表单数据提交时的验证,并且前端在表单中多增加一个隐藏字段,每当用户提交表单数据时(post请求),将这个隐藏字段一并提交,后端再对表单中的 ...
- Anaconda3(5-1)程序编辑器 自带的spyder
1装好后自带spyder编辑器 2 打开软件 3 每次程序需要制定anaconda3中创建的虚拟环境对应 的python版本的路径 例如在我的电脑我创建了两个环境 而我的pytorch安装在pytho ...
- Linux下进程间通信方式——信号量(Semaphore)
1.信号量 信号量本质上是一个计数器(不设置全局变量是因为进程间是相互独立的,而这不一定能看到,看到也不能保证++引用计数为原子操作),用于多进程对共享数据对象的读取,它和管道有所不同,它不以传送数据 ...