c语言:编译和链接(详解)

前言

要将编译和链接,就不得不提及编译器是如何运作的,虽然这部分知识是针对于要创造编译器和创作语言的人所需要清楚的,但作为c语言的学习者也需要了解一下,修炼内功,尤其是对于想学习c++的人而言。

编译器的运作过程大致分为翻译环境运行环境,翻译环境简单的说就是把你写的c语言(c++...)代码翻译成机器理解的二进制序列,并检查基本的语法等错误,最终通过链接生成一个可执行程序,

后缀为exe(windows)。运行化境就是载入内存开始执行程序,一般的越界访问和空指针引用就是在这个阶段发现的。

我们要讲的编译和链接就是在翻译环境中,翻译环境大致分为编译和链接两个过程,而编译又可以细分为预处理,编译,汇编三个过程。

编译

预处理

预处理又可以叫预编译,书籍中也有这种叫法,预处理主要处理那些源文件中#开始的预编译指令。比如:#include,#define,#if,#endif,处理规则如下:

1.将所有的#define删除,并展开所有的宏定义

2.处理所有的条件编译指令,如;#if,#endif....

3.处理#include的预编译指令,将包含的文件内容插入到该预编译指令的位置,也就是展开头文件。这个过程是递归进行的,也就是说被包含的头文件也可能包含其他文件,比如调用main函数之前,就会调用其他函数,也就是说main函数也是被其他函数调用的。

4.删除所有的注释

5.添加行号和文件名标识,方便后续编译器生成调试信息等

6.保留所有的#pragma的编译器指令,编译器后续会使用

在预处理阶段,源文件和头文件会被处理为.i后缀的文件。

经过预处理后的.i文件中不在包含宏定义,因为宏已经被展开。并前包含的头文件都被插入到.i文件中。所以当我们无法知道宏定义或者头文件是否包含正确的时候,可以查看预处理后的.i文件来确认。

编译

编译过程是将预处理后的文件进行一系列的:词法分析、语法分析、语义分析及优化,生成相应的汇编带文件。后缀为.s。

词法分析

将源代码程序输入扫描器,扫描器的任务就是简单的进行词法分析,把代码中的字符分割成一系列的记号(关键字、标识符、字面量、特殊字符)。

语法分析

语法分析用到语法分析器,将对扫描产生的记号进行语法分析,从而产生语法树。这些语法树是以表达式为结点的树。

语义分析

由语义分析器来完成,对表达式的语法层面分析。编译器所能做的分析是语义的静态分析。静态分析通常包括和类型的匹配,类型的转换等。这个阶段会报告错误的语法信息。

符号表

编译阶段会生成一个符号表,符号表的作用主要是为了汇编。

符号表的作用:

1.符号表提供了一些符号的定义信息(如类型、地址),帮助汇编器正确解析符号

2.符号表中记录了符号的地址信息(如函数地址,全局变量地址),汇编器根据符号表为符号分配具体的地址,并生成机器代码。

符号表的作用还有很多,这里简单了解即可,比如:在c++的函数重载就是一个典型例子,c语言规定函数的名字不可以一样。但是在c++,中却可以一样,这就是符号表起了作用,表明编译器在解释c++和c语言的时候,函数的解析规则时不同的,并不只是简单把函数名作为符号表。符号表的生成规则每个编译器都不太同,和编译器有关。

汇编

汇编是通过汇编器将汇编代码转换成机器可执行的指令(二进制),每一个汇编语句几乎都对应一条机器指令。这里不会做指令优化。结束时生成目标文件。

在windows系统下生成的目标文件后缀为.obj,在Linux系统下生成的目标文件后缀为.o。

链接

链接会把多个源文件和头文件链接在一起生成一个可执行程序,这是一个复杂的过程。

链接过程主要包括:地址和空间分配,符号决议和重定位等步骤。

链接解决的是一个项目中多个文件、模块之间相互调用的问题。
比如:函数定义的检查就是在链接阶段检查的

如图,.obj是windows系统下的目标文件,这就是在链接中发现的函数未定义错误。

总结

这里只是简单的介绍了编译器的编译和链接过程,具体的细节并没有提及,当然对于一般的学习者也不用了解的这么深,只用把大致了解就可以了。对于这部分学习是高度抽象的,因为很多部分就是底层机器的运行逻辑,很枯燥,甚至编译这部分单令出来就可以当成一门大学学科了,所以想要把这部分一下子全搞懂,不太现实,只能是干中学,一边写代码一边深入了解。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/894286.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

积分和微分的区别

积分: 积分是由微小量求大量,由微观的数据求得整体的状况。运算是对总量求和。 微分: 微分是由大量求微小量,反应微观的状况,运算是伴随着求导。 峰值检测电路: 上图检测的误差主要来自与二极管的正向导通电压降&am…

OVS-DPDK

dpdk介绍及应用 DPDK介绍 DPDK(Data Plane Development Kit)是一组快速处理数据包的开发平台及接口。有intel主导开发,主要基于Linux系统,用于快速数据包处理的函 数库与驱动集合,可以极大提高数据处理性能和吞吐量&…

亚博microros小车-原生ubuntu支持系列:18 Cartographer建图

Cartographer简介 Cartographer是Google开源的一个ROS系统支持的2D和3D SLAM(simultaneous localization and mapping)库。基于图优化(多线程后端优化、cere构建的problem优化)的方法建图算法。可以结合来自多个传感器&#xff0…

安卓(android)实现注册界面【Android移动开发基础案例教程(第2版)黑马程序员】

一、实验目的(如果代码有错漏,可查看源码) 1.掌握LinearLayout、RelativeLayout、FrameLayout等布局的综合使用。 2.掌握ImageView、TextView、EditText、CheckBox、Button、RadioGroup、RadioButton、ListView、RecyclerView等控件在项目中的…

爬虫基础(四)线程 和 进程 及相关知识点

目录 一、线程和进程 (1)进程 (2)线程 (3)区别 二、串行、并发、并行 (1)串行 (2)并行 (3)并发 三、爬虫中的线程和进程 &am…

自签证书的dockerfile中from命令无法拉取镜像而docker的pull命令能拉取镜像

问题现象: docker pull images拉取镜像正常 dockerfile中的from命令拉取镜像就会报出证书错误。报错信息如下: [bjxtbwj-kvm-test-jenkins-6-243 ceshi_dockerfile]$ docker build . [] Building 0.4s (3/3) FINISHED …

计算机网络 IP 网络层 2 (重置版)

IP的简介: IP 地址是互联网协议地址(Internet Protocol Address)的简称,是分配给连接到互联网的设备的唯一标识符,用于在网络中定位和通信。 IP编制的历史阶段: 1,分类的IP地址: …

面对企业文件交换难题,镭速跨网文件交换系统是如何解决的?

在当今这个数字化快速发展的时代,企业越来越依赖于数据交换来维持其业务运作。无论是内部网络之间的沟通还是与外部合作伙伴的数据共享,高效且安全的跨网文件交换都显得尤为重要。然而,在实际操作中,许多企业面临着各种各样的挑战…

Many Whelps! Handle It! (10 player) Many Whelps! Handle It! (25 player)

http://db.nfuwow.com/80/?achievement4403 http://db.nfuwow.com/80/?achievement4406 最少扣你50DKP! 第二阶段 当奥妮克希亚升空后,在10秒内引出50只奥妮克希亚雏龙,随后击败奥妮克希亚。 World of Warcraft [CLASSIC][80猎人][Grandel][最少扣你5…

自制虚拟机(C/C++)(一、分析语法和easyx运用,完整虚拟机实现)

网上对虚拟机的解释很多,其实本质就一句话 虚拟机就是机器语言解释器 我们今天要实现汇编语言解释器,下一次再加上ndisasm反汇编器就是真正虚拟机了 注:这里的虚拟机指的是VMware一类的,而不是JVM,python一样的高级语言解释器 …

36. printf

1. printf 格式化函数说的是 printf、 sprintf 和 scanf 这样的函数,分为格式化输入和格式化输出两类函数。学习 C 语言的时候常常通过 printf 函数在屏幕上显示字符串,通过 scanf 函数从键盘获取输入。这样就有了输入和输出了,实现了最基本…

实验八 JSP访问数据库

实验八 JSP访问数据库 目的: 1、熟悉JDBC的数据库访问模式。 2、掌握使用My SQL数据库的使用 实验要求: 1、通过JDBC访问mysql数据,实现增删改查功能的实现 2、要求提交实验报告,将代码和实验结果页面截图放入报告中 实验过程&a…

python学opencv|读取图像(四十六)使用cv2.bitwise_or()函数实现图像按位或运算

【0】基础定义 按位与运算:全1取1,其余取0。按位或运算:全0取0,其余取1。 【1】引言 前序学习进程中,已经对图像按位与计算进行了详细探究,相关文章链接如下: python学opencv|读取图像&…

使用vhd虚拟磁盘安装两个win10系统

使用vhd虚拟磁盘安装两个win10系统 前言vhd虚拟磁盘技术简介准备工具开始动手实践1.winX选择磁盘管理2.选择“操作”--“创建VHD”3.自定义一个位置,输入虚拟磁盘大小4.右键初始化磁盘5.选择GPT分区表格式6.右键新建简单卷7.给卷起个名字,用于区分8.打开…

基于云计算、大数据与YOLO设计的火灾/火焰目标检测

摘要:本研究针对火灾早期预警检测需求,采用在Kaggle平台获取数据、采用云计算部署的方式,以YOLOv11构建模型,使用云计算服务器训练模型。经训练,box loss从约3.5降至1.0,cls loss从约4.0降至1.0&#xff0c…

计算机毕业设计Python+CNN卷积神经网络考研院校推荐系统 考研分数线预测 考研推荐系统 考研爬虫 考研大数据 Hadoop 大数据毕设 机器学习

温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…

小程序-基础加强-自定义组件

前言 这次讲自定义组件 1. 准备今天要用到的项目 2. 初步创建并使用自定义组件 这样就成功在home中引入了test组件 在json中引用了这个组件才能用这个组件 现在我们来实现全局引用组件 在app.json这样使用就可以了 3. 自定义组件的样式 发现页面里面的文本和组件里面的文…

docker安装emqx

emqx安装 拉取emqx镜像 docker pull emqx/emqx:v4.1.0 运行docker容器 docker run -tid --name emqx -p 1883:1883 -p 8083:8083 -p 8081:8081 -p 8883:8883 -p 8084:8084 -p 18083:18083 emqx/emqx:v4.1.0 放行端口 1、如果要是自己的虚拟机,并且关闭了防火墙&a…

【4Day创客实践入门教程】Day4 迈向高手之路——进一步学习!

Day4 迈向高手之路——进一步学习! 目录 Day4 迈向高手之路——进一步学习!更多的开发板外壳制作 Day0 创想启程——课程与项目预览Day1 工具箱构建——开发环境的构建Day2 探秘微控制器——单片机与MicroPython初步Day3 实战演练——桌面迷你番茄钟Day4…

深度学习之“缺失数据处理”

缺失值检测 缺失数据就是我们没有的数据。如果数据集是由向量表示的特征组成,那么缺失值可能表现为某些样本的一个或多个特征因为某些原因而没有测量的值。通常情况下,缺失值由特殊的编码方式。如果正常值都是正数,那么缺失值可能被标记为-1…