我的编程空间,编程开发者的网络收藏夹
学习永远不晚

C/C++ - 从代码到可执行程序的过程详解

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

C/C++ - 从代码到可执行程序的过程详解

(1)预编译

主要处理源代码文件中的以“#”开头的预编译指令。处理规则见下:

删除所有的#define,展开所有的宏定义。处理所有的条件预编译指令,如“#if”、“#endif”、“#ifdef”、“#elif”和“#else”。处理“#include”预编译指令,将文件内容替换到它的位置,这个过程是递归进行的,文件中包含其
他文件。删除所有的注释,“//”和“”。保留所有的#pragma 编译器指令,编译器需要用到他们,如:#pragma once 是为了防止有文件
被重复引用。添加行号和文件标识,便于编译时编译器产生调试用的行号信息,和编译时产生编译错误或警告是
能够显示行号。

(2)编译

把预编译之后生成的xxx.i或xxx.ii文件,进行一系列词法分析、语法分析、语义分析及优化后,生成相应
的汇编代码文件。

词法分析:利用类似于“有限状态机”的算法,将源代码程序输入到扫描机中,将其中的字符序列分
割成一系列的记号。语法分析:语法分析器对由扫描器产生的记号,进行语法分析,产生语法树。由语法分析器输出的
语法树是一种以表达式为节点的树。语义分析:语法分析器只是完成了对表达式语法层面的分析,语义分析器则对表达式是否有意义进
行判断,其分析的语义是静态语义——在编译期能分期的语义,相对应的动态语义是在运行期才能
确定的语义。优化:源代码级别的一个优化过程。目标代码生成:由代码生成器将中间代码转换成目标机器代码,生成一系列的代码序列——汇编语
言表示。目标代码优化:目标代码优化器对上述的目标机器代码进行优化:寻找合适的寻址方式、使用位移
来替代乘法运算、删除多余的指令等。

(3)汇编

将汇编代码转变成机器可以执行的指令(机器码文件)。 汇编器的汇编过程相对于编译器来说更简单,没
有复杂的语法,也没有语义,更不需要做指令优化,只是根据汇编指令和机器指令的对照表一一翻译过
来,汇编过程有汇编器as完成。经汇编之后,产生目标文件(与可执行文件格式几乎一样)xxx.o(Windows 下)、xxx.obj(Linux下)。

(4)链接

将不同的源文件产生的目标文件进行链接,从而形成一个可以执行的程序。链接分为静态链接和动态链
接:

静态链接

函数和数据被编译进一个二进制文件。在使用静态库的情况下,在编译链接可执行文件时,链接器从库
中复制这些函数和数据并把它们和应用程序的其它模块组合起来创建最终的可执行文件。

以下面这个图来简单说明一下从静态链接到可执行文件的过程,根据在源文件中包含的头文件和程序中使用到的库函数,如stdio.h中定义的printf()函数,在libc.a中找到目标文件printf.o(这里暂且不考虑printf()函数的依赖关系),然后将这个目标文件和我们hello.o这个文件进行链接形成我们的可执行文件。

在这里插入图片描述

这里有一个小问题,就是从上面的图中可以看到静态运行库里面的一个目标文件只包含一个函数,如libc.a里面的printf.o只有printf()函数,strlen.o里面只有strlen()函数。

我们知道,链接器在链接静态链接库的时候是以目标文件为单位的。比如我们引用了静态库中的printf()函数,那么链接器就会把库中包含printf()函数的那个目标文件链接进来,如果很多函数都放在一个目标文件中,很可能很多没用的函数都被一起链接进了输出结果中。由于运行库有成百上千个函数,数量非常庞大,每个函数独立地放在一个目标文件中可以尽量减少空间的浪费,那些没有被用到的目标文件就不要链接到最终的输出文件中。

缺点:
空间浪费:因为每个可执行程序中对所有需要的目标文件都要有一份副本,所以如果多个程序对同一个
目标文件都有依赖,会出现同一个目标文件都在内存存在多个副本;
更新困难:每当库函数的代码修改了,这个时候就需要重新进行编译链接形成可执行程序。
运行速度快:但是静态链接的优点就是,在可执行程序中已经具备了所有执行程序所需要的任何东西,
在执行的时候运行速度快。

动态链接

动态链接的基本思想是把程序按照模块拆分成各个相对独立部分,在程序运行时才将它们链接在一起形成一个完整的程序,而不是像静态链接一样把所有程序模块都链接成一个单独的可执行文件。

假设现在有两个程序program1.o和program2.o,这两者共用同一个库lib.o,假设首先运行程序program1,系统首先加载program1.o,当系统发现program1.o中用到了lib.o,即program1.o依赖于lib.o,那么系统接着加载lib.o,如果program1.o和lib.o还依赖于其他目标文件,则依次全部加载到内存中。当program2运行时,同样的加载program2.o,然后发现program2.o依赖于lib.o,但是此时lib.o已经存在于内存中,这个时候就不再进行重新加载,而是将内存中已经存在的lib.o映射到program2的虚拟地址空间中,从而进行链接(这个链接过程和静态链接类似)形成可执行程序。

优点:
共享库:就是即使需要每个程序都依赖同一个库,但是该库不会像静态链接那样在内存中存在多分,副
本,而是这多个程序在执行时共享同一份副本;更新方便:更新时只需要替换原来的目标文件,而无需将所有的程序再重新链接一遍。当程序下一次运行时,新版本的目标文件会被自动加载到内存并且链接起来,程序就完成了升级的目标。
性能损耗:因为把链接推迟到了程序运行时,所以每次执行程序都需要进行链接,所以性能会有一定损失。

生成可执行文件

什么情况会编译成功但链接失败

(1)说明并使用了类型、函数、变量,但没给出相应类型、函数或变量的定义。关于说明和定义的区别见上述教程,说明可以通过#include头文件进行,也可以直接进行说明如int f( )或extern int f( )。若同时给出函数f的函数体则称为定义。对于变量若有初始值就算定义,例如"extern int x=3; "便是定义,这种语法有其独特应用背景。

(2)对标准库的连接失败,例如调用了sin(double x),却找不到数学运算标准库进行连接了,可能是安装后因各种可能原因被删除了。

(3)全局变量和静态变量存放在数据段,而固定大小的数据段不够用了,例如定义太多的全局变量和静态变量,甚至巨型数组全局或静态变量。

(4)数据段被偷用后无法容纳较多的全局变量和静态变量,这种错误最难发现且最难改正。主要是一些常量在偷用数据段,例如字符串常量"abc"等等,其它诸多情形参见上述教程。另外虚函数入口地址表等也会偷用。

到此这篇关于C/C++ - 从代码到可执行程序的过程的文章就介绍到这了,更多相关C++ 从代码到可执行程序的过程内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

C/C++ - 从代码到可执行程序的过程详解

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

C/C++ - 从代码到可执行程序的过程详解

这篇文章主要介绍了C/C++ - 从代码到可执行程序的过程,主要有预编译和编译,汇编链接,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
2023-01-15

深入解析golang编译器的编译过程:从源码到可执行文件

从源码到可执行文件:解析golang编译器的编译过程概述:Golang是一种快速、简单和可靠的编程语言,而其编译器是将Golang代码转换为可执行文件的关键工具。在这篇文章中,我们将深入探究Golang编译器的编译过程,从源码到最终生成的可
深入解析golang编译器的编译过程:从源码到可执行文件
2023-12-29

C语言从编译到运行的过程是什么

C语言从编译到运行的过程可以简单描述为以下几个步骤:1. 编写源代码:首先,程序员使用文本编辑器编写C语言源代码,包括各种语句和函数。2. 预处理:在源代码编译之前,需要进行预处理。预处理器会检查源代码中的预处理指令,并进行相应的处理。例如
2023-08-14

Java新手从代码到运行的过程是什么

本篇内容介绍了“Java新手从代码到运行的过程是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1:编写代码 首先把我们想要计算机做的事情
2023-06-17

C语言执行程序时遇到的常见问题及解决

这篇文章主要介绍了C语言执行程序时遇到的常见问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
2023-03-03

低代码从0到1创建小程序项目详解流程

低代码作为开发工具类的产品,需要有从0到1体系化的教程才可以,而且还得有教师进行辅助。否则,学习低代码是有难度的,入门很难。因为大家习惯了用代码编程,一下子过度到可视化编程,有一个思路上的转变
2022-11-13

Java计算代码段执行时间的详细过程

java里计算代码段执行时间可以有两种方法,一种是毫秒级别的计算,另一种是更精确的纳秒级别的计算,这篇文章主要介绍了java计算代码段执行时间,需要的朋友可以参考下
2023-02-07

C语言执行程序时遇到的常见问题如何解决

本文小编为大家详细介绍“C语言执行程序时遇到的常见问题如何解决”,内容详细,步骤清晰,细节处理妥当,希望这篇“C语言执行程序时遇到的常见问题如何解决”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。1.新命名一个头文
2023-07-05

C++ 函数调试详解:如何深入了解函数的执行过程?

c++++ 函数调试的关键技能包括:1. 设置断点以暂停执行;2. 单步执行逐行查看代码;3. 检查变量监视值;4. 打印调试信息查看特定状态。通过实战案例,可以深入了解函数执行过程,快速找出并修复错误。C++ 函数调试详解:深入函数执行过
C++ 函数调试详解:如何深入了解函数的执行过程?
2024-05-03

c语言从1加到100的编程代码是什么

从1加到100的编程代码是“int sum = 0;for (...) {sum += i;}printf("...", sum);return 0;”,详细步骤:1、定义变量“sum”存储累加结果;2、使用for循环来重复执行加法操作;3
2023-07-10

一篇文章带你了解Go到C的代码转换过程

随着软件开发的迅速发展,越来越多的编程语言涌现出来,每一种语言都有其独特的特点和优势。在开发过程中,有时候我们会面临将一个项目从一种编程语言转换成另一种编程语言的情况。本文将以Go语言转换为C语言为例,带您深入了解这一过程,并给出具体的代码
一篇文章带你了解Go到C的代码转换过程
2024-03-07

计算机中一个c程序的执行是从什么函数开始

小编给大家分享一下计算机中一个c程序的执行是从什么函数开始,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!一个c程序的执行是从本程序的main函数开始,到main函
2023-06-14

C语言三子棋的实现思路到过程详解

所谓三子棋,就是三行三列的棋盘,玩家可以和电脑下棋,率先连成三个的获胜。这篇文章主要为大家详细介绍了如何通过C语言实现三子棋小游戏,感兴趣的小伙伴可以尝试一下
2023-02-13

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录