编译链接过程详解

news2024/11/17 23:57:42

写在前面:
大家都知道,我们在编译器中建好一个**.c或.cpp 文件**,经过编译之后就可以运行了,也就是说我们写的.c 文件最后会变成一个可执行程序,那么 .c 或者 .cpp 文件是如何变成一个可执行程序的呢?
主要有以下四大步骤:

1、预编译
2、编译
3、汇编
4、链接

接下来我将会详细解释 编译链接 每一步

一、编译

编译过程分为两个阶段 编译汇编,编译主要就是 读取源程序(字符流),对之进行词法和语法的分析将高级语言指令转换为功能等效的汇编代码。

1.1 编译

编译又可以细分为两个小的步骤:预编译编译

1.1.1 预编译

因为需要做词法和语法的分析,因此需要预先处理我们编写的源程序中的 伪指令特殊符号进行处理,也就是大家比较熟知的 宏替换(#define A 10) 、头文件(#include<stdio.h>) 展开,还有一些特殊符号的处理。

1.1.1.1 伪指令是什么?

1.宏定义指令
例如 #define MaxNum 32 ,预编译要做的就是将源程序中的 MaxNum 全部替换成 32 ,但不会替换字符串常量"MaxNum" ,#undef 是取消某个宏定义,使在预编译时不会替换 MaxNum 为 32
例如:
在这里插入图片描述

2.条件编译指令
例如 #ifdef #else #endif #ifndef ,俗称条件编译,举个例子,现在我们有如下程序:

#include <stdio.h>
#define MaxNum 32
#undef MaxNum
#define HUAWEI 
void OpenDraw()
{
#ifdef HUAWEI
	printf("HuaWei");
#else 
	printf("notHuaWei");
#endif
}
int main()
{
	OpenDraw();
	return 0;
}

结果显而易见会打印出 Huawei
在这里插入图片描述
而如果没有

#define HUAWEI

那么显而易见 会打印
在这里插入图片描述
这样我们就可以宏来控制那一段代码会被编译,那一段不会编译,从而实现不同的需求

3.头文件包含指令
也就是大家都很熟悉的 #include<xxxxxx.h>,在预编译这个阶段会将头文件展开,意思就是 假如

#include <stdio.h>
int main()
{
	return 0;
}

假如头文件 <stdio.h> 有 1000 行的内容,那么这 1000行内容 都会展开并加到这个文件中进行编译。
例如 如下代码:

在这里插入图片描述
预编译之后查看 点 .i 文件 如下:

在这里插入图片描述
最后几行
在这里插入图片描述

1.1.1.2 特殊符号是什么?

看下面一段代码:

#include <stdio.h>
int main()
{
	printf("%d\n", __LINE__);
	printf("%s\n", __FILE__);
	printf("%s\n", __DATE__);
	return 0;
}

输出:
在这里插入图片描述
如上代码所示 __LINE__、__FILE__、__DATE__ 都是特殊符号,与此相同的还有

__FILE__ 包含当前程序文件名的字符串

__LINE__ 表示当前行号的整数

__DATE__ 包含当前日期的字符串

__STDC__ 如果编译器遵循ANSI C标准,它就是个非零值

__TIME__ 包含当前时间的字符串

这些特殊的符号会在预编译的时候替代

经过上面的预编译对伪指令和特殊符号处理,生成了一个没有伪指令、没有特殊符号的文件,接下来进行编译和优化阶段

1.1.2 编译

编译阶段的工作内容就是通过词法分析和语法分析,并做一些代码优化,详细的词法分析和语法分析不在此阐述,有兴趣的可以看 《编译原理》 这本书,在确认所有的指令都符合语法规则之后,将其翻译成等价的中间代码表示或汇编代码
查看 .s 文件
在这里插入图片描述

1.2 汇编

大家都知道计算机最底层其实是二进制的世界,而汇编就是将经过预编译、编译处理之后的文件转为二进制文件,例如linux 下经过逐步编译生成的二进制文件打开时这样的
linux 下生成的 .o 文件即为 二进制文件
在这里插入图片描述

二、链接

我们知道一般一个项目中会有很多很多的.cpp .h 还包括其他的第三方的一些库等等其他一切程序在执行中需要用到的东西,上述的预编译、编译、汇编,只是将一个个的.cpp 或者 .c 文件编译成 .o 二进制文件,这些还不能直接执行,就好比,一个汽车,虽然把每个零件都已经生产好了,但是没有组装,整合起来,这样这个汽车才能跑起来。
链接的工作就是将该程序相关的所有文件都链接起来
链接一般可以分为静态链接动态链接,这和我们常说的动态库静态库 又有什么关系呢

2.1 静态库与动态库

而库呢 什么叫库,我们写了一个打印 “helloworld” 功能的函数,并编译成 二进制代码,别人只需要在自己的文件中 #include 头文件,然后调用 函数 就可以 打印出 helloworld 了

什么时候我们会用到库呢?
一种情况是某些代码需要给别人使用,但是我们不希望别人看到源码,就需要以库的形式进行封装,只暴露出头文件
另外一种情况是,对于某些不会进行大的改动的代码,我们想减少编译的时间,就可以把它打包成库,因为库是已经编译好的二进制了,编译的时候只需要 Link 一下,不会浪费编译时间。

2.1.1 静态库

静态库即静态链接库(Windows 下的 .lib,Linux 和 Mac 下的 .a)例如:
在这里插入图片描述

2.1.2 动态库

动态库即动态链接库 (Windows 下的 .dll,Linux 下的 .so,Mac 下的 .dylib)
例如:
在这里插入图片描述

2.1 静态链接

1、静态库的链接
把调要调用的函数或者过程直接链接到可执行文件(dll或exe)中,成为可执行文件的一部分。该执行文件中包含了运行所需的全部代码(也就是说相当于把静态库中的全部代码拷过来了一样)。

优点:
链接该静态库的可执行文件(dll或exe等)使用时,无需再需要该静态库。
缺点:
a)当多个程序都要调用相同函数时,内存中就会存在这个函数的多个复制,存在资源浪费
b)当静态库发生修改时,不仅该静态库要从新编译,引用该静态库的模块都需要从新编译

2.2 动态链接

2、动态库的链接
动态链接调用的函数代码并没有被复制到应用程序的可执行文件中去,而是仅仅在其中加入了所调用函数的描述信息(往往是一些重定位信息)
仅当应用程序被装入内存开始运行时,在操作系统的管理下,才在应用程序与相应的动态链接库(dynamic link library,dll)之间建立链接关系
当要执行调用.dll文件中的函数时,根据链接产生的重定位信息,操作系统才转去执行.dll文件中相应的函数代码。
优点:
当修改动态库的代码,但重定位信息没有变化,引用该动态库的模块无需从新编译。当然,重定位信息发生改变,两者都需要从新编译。

2.3 动态库的链接方式

3、动态库链接的方式
1)LoadLibrary(根据路径加载动态库)、GetProcAddress(根据函数名获取函数指针,可能为空,但只能在运行时发现)、FreeLibrary(卸载动态库)
2)具有导出项的(DLL)动态链接库可根据导出的lib和头文件隐式链接,在编译阶段就可检查头文件和lib是否配套。运行时再保证动态库和lib配套即可。

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

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

相关文章

Vue计算属性和监视属性

目录 计算属性computed 监事属性 深度监视 计算属性computed 计算属性: 定义&#xff1a;要用的属性不存在&#xff0c;要通过已有属性计算得来 2、原理&#xff1a;底层借助了Object.defineproperty方法提供的getter和setter 3、get函数什么时候执行&#xff1f; 1、初…

移动硬盘修复的有效方法,恢复移动硬盘的数据这么做!

硬盘是计算机中的存储设备&#xff0c;是非常重要的部分。当硬盘发生故障&#xff0c;很可能会导致我们电脑里面的数据丢失。所以移动硬盘发生故障&#xff0c;我们一定要想办法修复它。 有没有什么操作方法&#xff0c;我们自己也可以简单进行&#xff1f;移动硬盘修复其实也…

mariadb数据库删除恢复过程

不作不死&#xff0c;不小心使sqlyog导数据选错服务器。把生产机的数据全部删除了。可怕的数据没有做其他过多的备份&#xff0c;只是每天自动crontab 备份。该怎么办呢&#xff1f;头脑一片空白。快&#xff0c; 赶紧看看日备份有没有。马上切换到备份目录&#xff0c;喜出望外…

构建指标体系是一套数据分析的框架,比如看哪些指标,这些指标变化了就会反映什么问题,是这样的吗?

指标体系是指由若干个反映企业业务运营特征的相对独立又相互联系的统计指标所组成的有机整体。近年来&#xff0c;各类企业逐渐认识到业务指标的重要性&#xff0c;从管理者们长期关注的企业绩效考核&#xff0c;到用来体现信息化水平的数据可视化大屏&#xff0c;其背后都离不…

【IoT】寻光智能车与循迹智能车

1、寻光智能车 功能说明 智能寻光小车&#xff0c;智能识别光线强弱&#xff0c;实现小车永远向光最强的地方行走&#xff0c;到光源处小车自动停止。基本车体为三轮、二驱、双层机构。主控芯片采用最常用的51单片机&#xff1b; 驱动采用L9110驱动芯片驱动两个减速直流电机…

Veeam ONE v12 发布 (含下载) - 面向所有工作负载的 IT 监控解决方案

Veeam Availability Suite v12 请访问原文链接&#xff1a;https://sysin.org/blog/veeam-one-12/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;www.sysin.org 概述 保持全面可视性和控制力&#xff0c;以高效执行管理、优化、计划和…

域渗透漏洞

一、域内提权漏洞 (CVE-2021-42287和CVE-2021-42278) 1.1 漏洞介绍 1.1.1 CVE-2021-42278 主机账户的名称尾部应该有一个 $(即 sAMAccountName 属性)&#xff0c;但是域控对此属性并没有任何验证来确保是否带有 $&#xff0c;这允许攻击者模拟域控主机账户。 1.1.2 CVE-2021-42…

python带你制作自动答题程序,速度超越98%人

前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! 目录前言环境使用:模块使用:自动答题思路步骤:代码展示尾语 &#x1f49d;环境使用: Python 3.8 –> 解释器 <执行python代码> Pycharm –> 编辑器 <写python代码的> 模块使用: import requests —&g…

Springboot_vue摄影作品图片展示交流平台

前后端通讯一般都是采取标准的JSON格式来交互。 前后端分离 的核心思想是前端页面通过 ajax 调用后端的 restuful api 进行数据交互&#xff0c;而 单页面应用&#xff08;single page web application&#xff0c;SPA&#xff09;&#xff0c;就是只有一张页面&#xff0c;并在…

https解决方案-利用keytool生成证书

https解决方案 1:什么是HTTPS&#xff1f; HTTPS其实是有两部分组成&#xff1a;HTTP SSL / TLS&#xff0c; 也就是在HTTP上又加了一层处理加密信息的模块&#xff0c;并且会进行身份的验证。 2:什么是自签名证书&#xff1f; 就是自己生成的证书&#xff0c;并不是官方…

计算机中的大小端存储

在讲C语言的时候&#xff0c;有讲到大小端的内容&#xff0c;这里呢对大小端的相关内容进行了整理&#xff0c;有需要的可以参考一下&#xff01; 大端和小端来自一个小故事&#xff1a;端模式(Endian)的这个词出自Jonathan Swift书写的《格列佛游记》。这本书根据将鸡蛋敲开的…

mysql导致索引失效的常见情况以及命名规范索引计划分析

1、失效的情况 1.前导模糊查询不能利用索引(like ‘%XX’或者like ‘%XX%’) 假如有这样一列code的值为’AAA’,‘AAB’,‘BAA’,‘BAB’ ,如果where code like %AB’条件&#xff0c;由于前面是 模糊的&#xff0c;所以不能利用索引的顺序&#xff0c;必须一个个去找&#xf…

虚拟机的Linux安装redis

1&#xff0c;下载redis 可以去官网下载压缩包 2&#xff0c;环境准备 我看很多文章都说要安装yum&#xff0c;但是在终端界面一直都是安装失败&#xff0c;后面才知道我的虚拟机是Ubuntu版本&#xff0c;而Ubuntu版本一般不使用yum命令&#xff0c;一般都是使用apt-get命令…

RANSAC: Random Sample Consensus

目录RANSAC算法基本思想和流程迭代次数推导参考RANSAC RANSAC(RAndom SAmple Consensus,随机采样一致)算法是从一组含有外点(outliers)的数据中正确估计数学模型参数的迭代算法。“外点”一般指的的数据中的噪声&#xff0c;比如说匹配中的误匹配和估计曲线中的离群点。所以&a…

电脑黑屏却开着机是怎么回事?解决黑屏的快捷方法

我们经常会用到电脑&#xff0c;但是你真的了解电脑相关知识吗&#xff1f;遇到比较复杂的电脑问题&#xff0c;你是否会手足无措&#xff1f;电脑黑屏却开着机这是什么原因造成的&#xff0c;我们有什么好办法恢复黑屏的电脑吗&#xff1f; 本文针对电脑黑屏却开着机的情况&a…

PCB生产工艺 | 第三道之沉铜,你都了解吗?

衔接上文&#xff0c;继续为朋友们分享普通单双面板的生产工艺流程。 如图&#xff0c;第三道主流程为沉铜。 沉铜的目的为&#xff1a; 在整个印制板&#xff08;尤其是孔壁&#xff09;上沉积一层薄铜&#xff0c;以便随后进行孔内电镀&#xff0c;使孔金属化&#xff08;孔…

小众点评项目要点内容总结【面试用】

小众点评项目要点 文章目录小众点评项目要点1.使用Redis代替Session登录1.1 Session登录存在的问题1.2 使用Redis代替Session登录分析1.3 使用Redis登录的流程1.4 解决Redis中有效期问题2.使用Redis作为缓存2.1 为什么使用缓存2.2 缓存策略2.3 解决缓存穿透2.4 解决缓存雪崩2.5…

CSS响应式设计——(视口/网格视图/媒体查询/图像/视频)看这一篇就够了

目录 响应式网页设计 - 简介 什么是响应式网页设计&#xff1f; 为所有用户获得最佳体验的设计 响应式网页设计 - 视口 什么是视口&#xff1f; 设置视口 把内容调整到视口的大小 响应式网页设计 - 网格视图 什么是网格视图&#xff1f; 构建响应式网格视图 实例 C…

【冷知识】如何快速获取自己的微信公众号关注页的链接地址?

一&#xff1a;业务场景 目前微信公众号的关注方法基本有三种: 扫描公众号二维码搜索公众号账号名称通过阅读公众号发布出来的公众图文,点击上面的微信号名称(右上角三点),可以查看公众号,进入关注页面。 但是如果想实现通过一个链接直接跳转到公众号的关注页面&#xff0c;…

VRP系统(视图介绍以及基本命令)

前言 VRP (Versatile Routing Platform)即通用路由平台&#xff0c;是华为在通信领域多年的研究经验结晶&#xff0c;是华为所有基于IP/ATM构架的数据通信产品操作系统平台。运行VRP操作系统的华为产品包括路由器、局域网交换机、ATM交换机、拨号访问服务器、IP电话网关、电信级…