C进阶—详解编译、链接
被隐藏了的过程
现如今在流行的集成开发环境下我们很少需要关注编译和链接的过程,而隐藏在程序运行期间的过程可不简单,即使使用命令行来编译一个源代码文件,简单的一句"gcc hello.c"命令就包含了非常复杂的过程。

1 #include<stdio.h>
3 int main()
4 {
5 printf("Hello word\n");
6 return 0;
7 }


在Linux系统下使用gcc编译程序时只须简单的命令:
$gcc hello.c
$/a.out
Hello word
不管哪种编辑器,以上过程可分为4个步骤,分别是预编译(Prepressing)、编译(Compilation)、汇编(Assembly)、链接(Linking)。

GCC 编译过程分解
预编译
首先是将源代码文件hello.h和相关的头文件,如stdio.h等被编译器Cpp预编译成一个.i文件。主要处理那些源文件中以“#”开始的预编译指令,如“#include"、”#define“等,主要规则如下:
将所有的”#define“删除,并且展开所有的宏定义。
处理所有条件预编译指令,比如”#if”、”#ifdef“、”#elif“等。
处理”#include“预编译命令,将被包含的文件插入到该预编译指令的位置。注意,这个过程是递归进行的,也就是说被包含的文件可能还包含其他文件。
删除所有的注释”//“和”/**/“。
添加行号和文件名标识,比如#2”hello.c“2,以便于编译器产生调试用时的行号信息及用于编译时产生编译错误或警告时能显示行号。
保留所有的#pragma编译器指令,因为预编译器需要用他们。
编译
编译过程就是把预处理完的文件进行一系列词法分析、语法分析、语义分析、生成汇编文件,这个过程是是整个程序构建的核心部分,也是最复杂的部分之一。gcc将预编译和编译合并成一个步骤,使用如下命令:
$gcc -s hello.c -o hello.s
可得到会变输出文件 hello.s 。实际上gcc这个命令只是这些后台程序的包装,它会根据不同的参数要求去调用预编译编译程序cc1、汇编器as、链接器ld。
编译器职责
词法分析 经过预编译的源代码程序被输入到扫描器(Scanner),扫描器对其进行简单的词法分析,运用一种类似于有限状态机的算法将源代码的字符列分割成一系列的记号。如:关键字、标识符、字面量(包含数字、字符串等)和特殊符号(如加号、等号)。在标别记号的同时扫描器也完成了其他如将标识符存放到符号表,将数字、字符串常量存放到文件表等的工作,以备后面的步骤使用。(lex程序可实现词法扫描,按照一定的词法规则完成标别记号等功能,所以无需为每个编译器开发一个独立此法扫描器,而是根据需要改变语法规则即可。)
语法分析 语法分析器采用上下文无关语法的分析手段对扫描器产生的记号(Token)进行语法分析,从而生成语法树,即一表达式为节点的树。同时很多运算符的含义和优先级也被确定下来。编译器也会报告出语法分析阶段的错误。(如词法分析有像lex一样语法分析有现成工具ycc,它可根据语法规则对输入的记号序列构建出一颗语法树。对不同的编程语言只须改变语法规则即可。)
语义分析 语义分析由语义分析器完成,它所能分析的语义是静态语义,即编译期间可以确定的语义,运行期间才能确定的语义是指动态语义。静态语义通常包括生命和类型匹配,类型转换,如浮点型到整型转换。经过语义分析以后整个语法树都被标识了类型,如果有些类型需要做隐式转换,语义分析程序会在语法树中插入相应的转换节点。语义分析器对符号表里的符号类型也做了更新。语法分析仅仅完成对表达式语法层面的分析, 该语句是否有意义不进行检测。
符号汇总 源码优化器会在源代码级别进行优化,它往往将整个语法树转换成中间代码,它是语法树的顺序表示,已非常接近目标代码。中间代码有多种类型,常见的有三地址码,P-代码。中间代码使得编译器可分成前端和后端,前段即产生中间代码,后端将中间代码转换成目标机器代码。编辑器主要包括代码生成器和目标代码生成器。代码生成器将中间代码转换成目标机器代码。目标代码优化器再对其进行优化,如选择合适的寻址方式、使用位移来代替乘法运算、删除多余指令等。
汇编
汇编器是将汇编代码变成机器可以执行的指令,每一条汇编指令几乎都对应一条机器指令,根据其对照表一一翻译即可。目标文件中还包括链接是所需要的一些调试信息: 比如符号表、 调试信息、 字符串等。
链接
人们把每个源代码模块独立的进行编译,然后按照需要将它们组装起来,这个组装的过程就是链接(Linking)。
未解决的符号表: 列出本单元里有引用但是不在本单元定义的符号以及地址。导出符号表: 本单元中定义的一些符号(全局、静态变量和函数) 和地址的映射表。地址重定向表: 提供了本编译单元所有对自身地址的引 用记录。连接器的工作顺序:当连接器链接的时候, 首先决定各个目标文件在最终可执行文件里的位置。然后访问所有目标文件的地址重定义表, 对其中记录的地址进行重定向 (加上一个偏移量, 即该编译单元在可执行文件上的起始地址) 。然后遍历所有目标文件的未解决符号表, 并且在所有的导出符号表里查找匹配的符号, 并在未解决符号表中所记录的位置上填写实际地址。最后把所有的目标文件的内容写在各自的位置上,和库(Library)一起链接,形成最终的可执行文件。
总结:

C进阶—详解编译、链接的更多相关文章
- Jenkins企业应用进阶详解(一)
Jenkins企业应用进阶详解(一) 链接:https://pan.baidu.com/s/1NZZbocZuNwtQS0eGkkglXQ 提取码:z7gj 复制这段内容后打开百度网盘手机App,操作 ...
- L011系统文件属性知识进阶详解小节
L011系统文件属性知识进阶详解小节 这节课的内容相对来说较少,一上午加中午就听完了,现在总结一下,最后会有一个相关的面试题. 首先先附上一张图: 今天学习主要跟①和②有关,①为Inode 号 ②为文 ...
- Linux 链接详解----静态链接实例分析
由Linux链接详解(1)中我们简单的分析了静态库的引用解析和重定位的内容, 下面我们结合实例来看一下静态链接重定位过程. /* * a.c */ ; void add(int c); int mai ...
- shell脚本进阶 详解及其实例(一)
v\:* {behavior:url(#default#VML);} o\:* {behavior:url(#default#VML);} w\:* {behavior:url(#default#VM ...
- 【FPGA篇章六】FPGA编译向导:详解编译预处理功能
欢迎大家关注我的微信公众账号,支持程序媛写出更多优秀的文章 Verilog HDL语言和C语言一样也提供了编译预处理功能. Verilog HDL允许在程序中使用特殊的编译预处理语句. 在编译时,通常 ...
- Linux ll查看文件属性详解-软硬链接详解
Linux文件属性及类型 [root@localhost ~]# ll anaconda-ks.cfg 文件类型 权限 硬连接数 文件的大小 文件的创建,修改时间 - rw-------. 1 roo ...
- T-SQL查询进阶--详解公用表表达式(CTE)
简介 对于SELECT查询语句来说,通常情况下,为了使T-SQL代码更加简洁和可读,在一个查询中引用另外的结果集都是通过视图而不是子查询来进行分解的. 但是,视图是作为系统对象存在数据库中,那对于结果 ...
- pm2 start命令进阶详解
在node的世界里面,并不存在nginx或者apache,甚至tomcat这种东东.一个node,本身就用几行代码,就可以启动个server进程,监听个端口,为大家提供web服务.这和传统的网站代码的 ...
- Python进阶——详解元类,metaclass的原理和用法
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是Python专题第18篇文章,我们来继续聊聊Python当中的元类. 在上上篇文章当中我们介绍了type元类的用法,在上一篇文章当中我 ...
随机推荐
- CentOS7 搭建Ambari-Server,安装Hadoop集群(一)
2017-07-05:修正几处拼写错误,之前没发现,抱歉! 第一次在cnblogs上发表文章,效果肯定不会好,希望各位多包涵. 编写这个文档的背景是月中的时候,部门老大希望我们能够抽时间学习一下Had ...
- CSS边框(圆角、阴影、背景图片)
1.圆角 border-radius是向元素添加圆角边框. 使用方法: border-radius:10px; /* 所有角都使用半径为10px的圆角 */ border-radius: 5px 4 ...
- SQL Prompt 破解之道
1. 下载SQL Prompt 5.3.4.1,是个压缩包,里面有三个文件 免登录免积分下载地址:http://download.csdn.net/detail/caizz520/4557385 1) ...
- jquery html5 file 上传图片显示图片
jquery js 的代码:不同浏览器下的路径 //建立一個可存取到該file的url function getObjectURL(file) { var url = null ; i ...
- Java设计模式之适配器模式(项目升级案例)
今天是我学习Java设计模式中的第三个设计模式了,但是天气又开始变得狂热起来,对于我这个凉爽惯了的青藏人来说,又是非常闹心的一件事儿,好了不管怎么样,目标还是目标(争取把23种Java设计模式接触一遍 ...
- 【HTML】ie=edge(转)
< meta http-equiv = "X-UA-Compatible" content = "IE=edge,chrome=1" /> 这是个是 ...
- 【MYSQL】ubuntu13安装mysql(转)
安装的是mysql-5.0.87-linux-i686-glibc23.tar.gz 1.解压tar.gz tar –xzf mysql-5.0.87-linux-i686-glibc23.tar.g ...
- Making the Grade (bzoj1592)
题目描述 FJ打算好好修一下农场中某条凹凸不平的土路.按奶牛们的要求,修好后的路面高度应当单调上升或单调下降,也就是说,高度上升与高度下降的路段不能同时出现在修好的路中. 整条路被分成了N ...
- 为Tornado框架加上基于Redis或Memcached的session 【第三方】
Tornado 没有session,只有cookie_secret,这在一些情况下是不利于开发的.所有我们可以给Tornado加上session的功能. 这篇文章讲解的是依靠第三方包来实现.以后的文章 ...
- null == undefined ?
最近在看<JavaScript高级程序设计>一书,书中讲到相等操作符(==)时说,要比较相等性之前,不能将 null 和 undefined 转换成其他任何值,但要记住 null == u ...