C/C++预编译、编译、汇编和链接四个过程

本文详细阐述了C/C++编程中预编译、编译、汇编和链接四个步骤,从预处理的宏展开、条件编译到编译阶段的词法、语法和语义分析,再到汇编器将汇编代码转化为机器指令,最后链接器整合目标代码、启动代码和库函数生成可执行文件。理解这一过程对于优化代码和排查错误至关重要。
摘要由CSDN通过智能技术生成

目录

一,预编译(预处理Preproceessing)

二,编译(Compilation)

词法分析

语法分析

语义分析

代码优化

代码生成

三、汇编(Assembly)

四、链接(Linking) 


C/C++编程的基本策略:用程序将源代码文件转换为可执行文件(其中包含可直接运行的机器语言代码)
典型的C实现通过编译链接两个步骤来完成。

  • 编译器把源代码转化成中间代码
  • 链接器把中间代码和其他代码合并,生成可执行文件

 编译链接过程要细分的话要分解4个步骤:预处理、编译、汇编、链接。而用GCC来编译这个“hello world”程序的过程为下图: 

 编译链接流程:

一,预编译(预处理Preproceessing

由源文件“.cpp/.c”生成“.i”文件。

总的来说就是:

  • 处理“#”开头的关键字
  • 删除注释,添加行号和文件标识。

详细过程:

  • (1)将所有的#define删除,并且展开所有的宏定义。说白了就是字符替换
  • (2)处理所有的条件编译指令,#ifdef #ifndef #endif等,就是带#的那些
  • (3)处理#include,将#include指向的文件插入到该行处。这个过程是递归进行的,也就是说被包含的文件可能还包含其他文件。 
  • (4)删除所有注释
  • (5)添加行号和文件标识,这样的在调试和编译出错的时候才知道是是哪个文件的哪一行
  • (6)保留#pragma编译器指令,因为编译器需要使用它们。

缺点:不进行任何安全性及合法性检查

二,编译(Compilation

由“.i”文件生成“.s”文件,编译是对于预处理完的文件进行一些列的词法分析语法分析语义分析优化后产生相应的汇编代码文件。内联函数的替换就发生在这一阶段

主要功能:

词法分析

识别单词,确认词类;比如int i;知道int是一个类型,i是一个关键字以及判断i的名字是否合法。

将源代码文件的字符序列划分为一系列的记号,一般词法分析产生的记号有:标识符、关键字、数字、字符串、特殊符号(加号、等号)在识别记号的同时也将标识符放入符号表、将数字、字符放入到文字表等;有一个lex程序可以实现词法扫描,会按照之前定义好的词法规则将输入的字符串分割成记号,所以编译器不需要独立的词法扫描器;

 语法分析

识别短语和句型的语法属性;

语法分析器将对产生的记号进行语法分析,产生语法树----就是以表达式尾节点的树,一步步判断如何执行表达式操作。如果存在括号不匹配或者表达式错误,编译器就会报告语法分析阶段的错误;相同的存在一个yacc程序可以根据用户输入的语法规则生成语法树

语义分析

确认单词、短语和句型的语义特征;

由语法阶段完成分析的并没有赋予表达式或者其他实际的意义,比如乘法、加法、减法,必须经过语义阶段才能赋予其真正的意义;语义分析主要分为静态语义动态语义两种;

  • 静态语义通常包括声明和类型的匹配、类型的转换。比如当一个浮点型的表达式赋值给一个整型的表达式时,其中隐含了一个浮点型到整型转换的过程。只要存在类型不匹配编译器会报错。经过语义分析后的语法树的所有表达式都有了类型。
  • 动态语义分析只有在运行阶段才能确定;

代码优化

修辞、文本编辑;


代码生成

生成译文。

三、汇编(Assembly)

汇编器是将汇编代码转化成机器可以执行的命令,每一条汇编语句都对应一条机器指令,并生成可重定位目标程序的.o文件,该文件为二进制文件,字节编码时机器指令。汇编相对于编译的过程比较简单,根据汇编指令表和机器指令表一一进行翻译就可以了。所以汇编器的汇编过程相对与编译器是比较简单的

四、链接(Linking) 

链接分为:静态链接、动态链接。 
静态链接:在编译阶段就把静态库就加到可执行文件中去,这样可执行文件就会比较大。 
动态链接:在链接阶段仅仅只加入一些描述信息,而程序执行时再从系统中把相应动态库加载到内存中去。 
链接时通过调用连接器来链接程序运行需要的一大堆目标文件,以及所依赖的其他库的文件,最后生成可执行文件。链接程序的主要工作就是将有关的目标文件彼此相连接,也就是将在一个文件中引用的符号同该符号在另外一个文件中的定义连接起来,使得所有的这些目标文件成为一个能够被操作系统装入执行的统一整体。 

在编译之后,将源代码转换成汇编代码,然后通过汇编,将汇编代码转换成机器语言代码(目标代码)。

  1. 目标代码缺失启动代码(startup code)。启动代码充当着程序和操作系统直接的接口。在不同的操作系统下,目标代码相同,但系统启动代码不同,因为系统处理程序的方式不同。
  2. 目标代码还缺少库函数。几乎所有的C程序都要使用C标准库中的函数。
  3. 链接器的作用就是:把编写的目标代码、系统的标准启动代码库代码这三部分合并成一个文件,即可执行文件(.exe)。对于库代码,链接器只会把要用到的库函数代码提取出来。

我们编写的程序代码是怎样运行起来的?到底运行的是什么内容?

用编译链接过程回答

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SOC罗三炮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值