【C语言】编译与链接

1.翻译环境与运行环境

在ANSI C的任何一种实现中,存在两个不同的环境。

1.翻译环境,在这个环境中源代码被转换为可执行的机器指令(二进制指令)

2.执行环境,它用于实际执行代码

 

 2.翻译环境

那么翻译环境是怎么将源代码转换为可执行的机器指令的呢?这里我们就得展开讲解一下翻译环境所做的事情。

其实翻译环境由编译链接两个大的过程组成,而编译又可以分解成三个部分:预处理(也叫预编译)、编译、汇编。

一个C语言的项目中可能由多个.c文件一起构建

多个.c文件生成可执行程序又可分为一下几个步骤:
多个. c文件单独经过编译器,编译处理生成对应的目标文件(在windows环境下目标文件的后缀是.obj,Linux环境下目标文件的后缀是.o)。

多个目标文件和链接库一起经过链接处理生成最终的可执行程序(链接库是指运行库(它是支持程序运行的基本函数集合)或者第三方库)。

如果再把编译器展开成三个过程,那就变成了下面的过程:

2.1 预处理(预编译)

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

gcc环境下观察一下,对test.c文件预处理后的.i文件,命令如下:

gcc  -E  test.c  -o test.i

预处理阶段主要处理那些源文件中#开始的预处理指令,比如:#include,#define,处理的规则如下:

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

处理所有的条件编译指令,如#if,#iddef,#elif,#endif

处理#include预编译指令,将包含的头文件的内容插入到该预编译指令的位置。这个过程是递归进行的,也就是说被包含的头文件也可能包含其他文件。

删除所有的注释(也就是你对代码的解释,即//后面的文字)

比如:

test.c中的代码为:

#include<stdio.h>
int main()
{printf("hello world");//打印hello worlereturn 0;
}

在生成的test.i中就会把注释删掉

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

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

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

 2.2 编译

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

编译过程的命令如下:

gcc -S test.i -o test.s

 那么对下面代码进行编译的时候,会这么做呢?

array[index]=(index+4)*(2+6)

首先对其进行词法分析 

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

对上面代码进行词法分析得到了16个记号:

接下来进行语法分析:

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

最后进行语义分析:

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

(如果想要进一步了解编译过程,可以去看看《编译原理》这一本书) 

2.3 汇编

汇编器是将汇编代码转变成为机器可执行的指令,每一个汇编语句几乎都对应一条机器指令(二进制指令)。就是根据汇编指令和机器指令的对照表一一的进行翻译,也不做指令优化。

汇编的命令如下:

gcc -c test.s -o test.o

2.4 链接

链接是一个复杂的过程,链接的时候需要把一堆文件链接在一起才可以生成可执行程序。

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

链接解决的是一个项目多文件、多模块之间相互调用的问题。

比如:

在一个c项目中有两个.c文件(test.c和add.c),代码如下:
test.c:

#include <stdio.h>
//test.c
//声明外部函数
extern int Add(int x, int y);
//声明外部的全局变量
extern int g_val;
int main()
{int a = 10;int b = 20;int sum = Add(a, b);printf("%d\n", sum);return 0;
}

add.c:

int g_val = 2022;
int Add(int x, int y)
{return x+y;
}

 我们已经知道,每个源文件都是单独经过编译器处理形成对应的目标文件。

test.c经过编译处理生成test.o

add.c经过编译处理生成add.o

我们在test.c文件中使用了add.c文件中的Add函数和g_val变量。

我们在test.c文件每一次使用Add函数和g_val的时候必须确切的知道Add和g_val的地址,但是由于每个文件是单独编译的,在编译器编译test.c的时候并不知道Add函数和g_val变量的地址,所以暂时把Add的指令的目标地址和g_val的地址搁置。等待最后链接的时候由编译器等根据引用的符号Add在其他模块查找Add函数的地址,然后将test.c中所有引用到Add的指令重新修正,让他们的目标地址成为真正的Add函数的地址,对于全局变量g_val也是类似的方法来修正地址。这个地址修正的过程也被叫做:重定位。

3. 运行环境

1.程序必须载入内存中。在由操作系统的环境中:一般这个由操作系统完成。在独立的环境中,程序的载入必须由手工安排,也可能是通过可执行代码置入只读内存来完成。

2.程序开始执行代码。接着使用main函数。

3.开始执行程序代码。这个时候程序将使用一个运行时堆栈(stack),存储函数局部变量和返回值地址。程序同时也可以使用静态(static)内存,存储于静态变量在程序的整个执行过程一直保留他们的值。

4.终止程序。正常终止main函数,也有可能时意外终止。

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

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

相关文章

Java:七大基于比较的排序算法——上(思想+代码实现 超详细!)

冒泡排序、堆排序、插入排序、归并排序、快速排序、选择排序、希尔排序 目录 一、冒泡排序 1、基本思想 2、特征总结 3、代码实现 二、堆排序 1、基本思想 2、特征总结 3、代码实现 三、插入排序 1、基本思想 2、特征总结 3、代码实现 四、选择排序 1、基本思想 …

带宽的理解-笔记

带宽的理解 带宽(频带宽度)&#xff1a;是指电磁波最高频率和最低频率的差值&#xff0c;这一段频率被称为带宽。 举例说明 人耳能听到的频率范围是20赫兹到2万赫兹。换句话说&#xff0c;人而只对20赫兹至2万赫兹的声音频率有反应&#xff0c;超出或低于这一频率范围的声音我…

上市企业数字赋能指数数据集-2001到2022年(TF-IDF)

01、数据简介 上市公司数字赋能指数是一个用来衡量上市公司利用数字技术提高业务能力和效率的指标。这个指数反映了上市公司利用大数据、云计算和人工智能等数字技术&#xff0c;高效地利用商业资源和信息&#xff0c;并扩展供应关系的能力。市公司数字赋能指数是一种综合性的…

小米汽车充电枪继电器信号

继电器型号&#xff1a; 参考链接 小米SU7&#xff0c;便捷充放电枪拆解 (qq.com)https://mp.weixin.qq.com/s?__bizMzU5ODA2NDg4OQ&mid2247486086&idx1&sn0dd4e7c9f7c72d10ea1c9f506faabfcc&chksmfe48a110c93f2806f6e000f6dc6b67569f6e504220bec14654ccce7d…

基于Spring Boot的家具销售电商平台设计与实现

基于Spring Boot的家具销售电商平台设计与实现 开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/idea 系统部分展示 系统功能界面图&#xff0c;在系统首页可以查看首页…

PDF 正确指定页码后,挂载的书签页码对不上

这个问题与我的另一篇中方法一样 如何让一个大几千页的打开巨慢的 PDF 秒开-CSDN博客 https://blog.csdn.net/u013669912/article/details/138166922 另作一篇的原因 一篇文章附带一个与该文章主题不相关的问题时&#xff0c;不利于被遇到该问题的人快速搜索发现以解决其遇到…

JavaScript基础(二)

JS语法结构——引入方式 js很明显可以是一个后缀名为js的文件&#xff0c;js的引入方式和css一样&#xff0c;也有三种方式。 1.外部 使用script表现&#xff0c;只不过增加一个src属性&#xff0c;把js文件的路径src属性中。 <script src "js文件路径">&l…

查看笔记本电池容量/健康状态

1. 打开命令行提示符 快捷键“win R”后输入“cmd” 2. 在命令提示符中输入命令 “powercfg /batteryreport" 并回车 3. 查看文件 最后就可以看到笔记本的电池使用报告了

[华为OD] C卷 5G网络 现需要在某城市进行5G网络建设,已经选取N个地点设置5G基站 200

题目 现需要在某城市进行5G网络建设&#xff0c;已经选取N个地点设置5G基站&#xff0c;编号固定为1到N,接 下来需要各个基站之间使用光纤进行连接以确保基站能互联互通&#xff0c;不同基站之间架设光纤的成 本各不相同&#xff0c;且有些节点之间已经存在光纤相连&#…

mongodb使用debezium

前置 服务器上需要安装jdk11 jdk下载地址 kafka安装 官网下载地址 安装教程 debezium 安装 运行 Debezium 连接器需要 Java 11 或更高版本 Debezium 并不是一个独立的软件&#xff0c;而是很多个 Kafka 连接器的总称。这些 Kafka 连接器分别对应不同的数据库&#xff0c;…

十一、大模型-Semantic Kernel与 LangChain 的对比

Semantic Kernel 与 LangChain 的对比 Semantic Kernel 和 LangChain 都是用于开发基于大型语言模型&#xff08;LLM&#xff09;的应用程序的框架&#xff0c;但它们各有特点和优势。 基本概念和目标 Semantic Kernel 是一个由微软开发的轻量级 SDK&#xff0c;旨在帮助开发…

uniapp 自定义 App启动图

由于uniapp默认的启动界面太过普通 所以需要自定义个启动图 普通的图片不可以过不了苹果的审核 所以使用storyboard启动图 生成 storyboard 的网站&#xff1a;初雪云-提供一站式App上传发布解决方案

短视频素材哪个App最好?短视频素材哪里有免费的?

在数字媒体的黄金时代&#xff0c;富有创意的视频内容已成为吸引观众的关键。高质量的视频素材不仅能增强视觉效果&#xff0c;还能提升整体叙述的力度。以下列出了一系列全球顶尖的视频素材提供网站&#xff0c;它们将为你的广告制作、社交媒体或任何视频项目提供极具影响力的…

C++浮点数format时的舍入问题

C浮点数format时的舍入问题 首先有这样一段代码&#xff1a; #include <iostream> #include <stdio.h> using namespace std;int main() {cout << " main begin : " << endl;printf("%.0f \r\n", 1.5);printf("%.0f \r\n&…

jenkins教程

jenkins 一、简介二、下载安装三、配置jdk、maven和SSH四、部署微服务 一、简介 Jenkins是一个流行的开源自动化服务器&#xff0c;用于自动化软件开发过程中的构建、测试和部署任务。它提供了一个可扩展的插件生态系统&#xff0c;支持各种编程语言和工具。 Jenkins是一款开…

ROM修改进阶教程------如何去除安卓机型系统的开机向导 几种操作步骤解析

在和很多工作室定制化系统中。手机在第一次启动的时候系统都会进入设置向导,虽然可以设置手机的基本配置。但有很多客户需要去除手机的开机向导来缩短开机时间。确保手机直接进入工作状态。那么今天的教程针去除对开机向导的几种方法做个解析。机型很多版本不同。操作也有不同…

ENVI下遥感积雪面积信息的提取

积雪是气温、降水变化的最敏感的指示因子之一&#xff0c;ENVI为积雪面积信息的提取提供了多种技术方法 光谱统计学方法 光谱统计学提取积雪面积信息主要利用感兴趣区域ROI&#xff08;样本&#xff09;的选择&#xff0c;利用传统的监督方法实现。 决策树方法 决策树方法提取…

《HCIP-openEuler实验指导手册》1.7 Apache虚拟主机配置

知识点 配置步骤 需求 域名访问目录test1.com/home/source/test1test2.com/home/source/test2test3.com/home/source/test3 创建配置文件 touch /etc/httpd/conf.d/vhost.conf vim /etc/httpd/conf.d/vhost.conf文件内容如下 <VirtualHost *.81> ServerName test1.c…

翻译: 什么是ChatGPT 通过图形化的方式来理解 Transformer 架构 深度学习二

合集 ChatGPT 通过图形化的方式来理解 Transformer 架构 翻译: 什么是ChatGPT 通过图形化的方式来理解 Transformer 架构 深度学习一翻译: 什么是ChatGPT 通过图形化的方式来理解 Transformer 架构 深度学习二翻译: 什么是ChatGPT 通过图形化的方式来理解 Transformer 架构 深…

阿里云开源大模型开发环境搭建

ModelScope是阿里云通义千问开源的大模型开发者社区&#xff0c;本文主要描述AI大模型开发环境的搭建。 如上所示&#xff0c;安装ModelScope大模型基础库开发框架的命令行参数&#xff0c;使用清华大学提供的镜像地址 如上所示&#xff0c;在JetBrains PyCharm的项目工程终端控…