草庐IT

【C语言深度解剖】一篇解决程序的环境【编译+链接详解】让面试官给我们竖起大拇指

@背包 2023-04-10 原文


文章目录


【C语言深度解剖】【Linux操作系统】程序的环境【编译+链接详解】
那么这里博主先安利一下一些干货满满的专栏啦!

作者: #西城s
这是我的主页:#西城s
在食用这篇博客之前,博主在这里介绍一下其它高质量的编程学习栏目:
数据结构专栏:数据结构 这里包含了博主很多的数据结构学习上的总结,每一篇都是超级用心编写的,有兴趣的伙伴们都支持一下吧!
算法专栏:算法 这里可以说是博主的刷题历程,里面总结了一些经典的力扣上的题目,和算法实现的总结,对考试和竞赛都是很有帮助的!
力扣刷题专栏Leetcode想要冲击ACM、蓝桥杯或者大学生程序设计竞赛的伙伴,这里面都是博主的刷题记录,希望对你们有帮助!
C的深度解剖专栏:C语言的深度解剖想要深度学习C语言里面所蕴含的各种智慧,各种功能的底层实现的初学者们,相信这个专栏对你们会有帮助的!

今天博主将带大家详细深入地解剖C程序编译的过程,这些是我们内功修炼的必要知识,学会这些,让面试官给你竖起大拇指。

不收藏必后悔系列篇~

程序的翻译环境

  • 在ANSI C的任何一种实现中,存在两个不同的环境。
    第1种是翻译环境,在这个环境中源代码被转换为可执行的机器指令(.exe)
    第2种是执行环境,它用于实际执行代码。

即:

翻译环境详解

首先,我们知道编译这个过程,可以将test.c变成test.exe,那么,在此期间的过程,我们也要深入研究。

翻译环境基本原理:
每个源文件单独经过编译器处理后,生成相对应的目标文件(.obj)之后,结合链接库,经过编译器处理后,形成可执行程序(.exe)

IDE介绍:

VS2022
DEV C++
CodeBlocks
Clion
集成开发环境-IDE
继承了编辑,编译,链接,调试等功能

这些IDE里面在下载的时候都一定带有两个可执行程序
cl.exe(编译器),link.exe(编译器)

具体过程如下:
如图:

  • test.c----test.obj
    contact.c-----contact.obj
    每个源文件经过编译器生成对应的目标文件(.obj)文件之后
    加上链接库经过链接器—可执行程序(链接库:库函数等)

编译

编译:预处理+编译+汇编
经过上述阶段之后,我们就可以得到.obj文件了。

讲解代码:
我们创建两个源文件test.cadd.c
test.c:

extern int Add(int, int);
int main() {
	int a = 10;
	int b = 20;
	int c = Add(a, b);
	printf("%d\n", c);
	return 0;
}

add.c:

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

我们就用这两个简单的代码给大家解释编译的详细过程,以及预处理,编译,汇编的每一步的结果

  • 由于VS等IDE软件已经高度集成,我们无法看到编译中间的详细过程,因此博主在这里使用linux操作系统下的gcc编译器为大家演示。

我们先写好代码:
使用vim编辑器编辑源文件:



写好代码,我们先跑一次,看看有没有问题出现先,后面我们再拆开每一步讲解:

我们可以看到,结果是30。说明没问题,ok,我们开始拆解编译过程。

预编译

为了更好的观察每一个步骤,这里食用Linux gcc来演示
gcc test.c -E (在预编译之后停下来)
再-o 放到test.i里面
所以
gcc test.c -E -o test.i
vim打开来观察一下

预编译结果:

预编译结果其实完成了这么几件事情:

编译

指令:-S
结果:生成一个.i文件,里面是汇编代码
所以在这时期:把C语言代码翻译成了汇编代码

  1. 语法词法分析
  2. 语义分析
  3. 符号汇总(把一些全局的符号汇总起来,为下一步汇编时符号表的生成做准备

汇编

指令: -c
结果:生成test.o文件
windows环境下:目标文件xxx.obj
linux环境下:目标文件xxx.o
目标文件是二进制的—是看不懂的
此过程

  • 把汇编指令翻译成二进制指令

完成的东西:

  • 形成符号表


关于形成符号表

在汇编这个过程,符号表的形成时需要我们理解的,这是在为链接做准备。
形成符号表是啥意思呢?

  • 简单来说就是让全局的符号形成一个符号和地址的表:比如Add,因为这个符号是要跨文件使用的,test.c里要用,add.c里也要用,这些符号是要形成符号表的,但是add.c里面的临时变量x,y这些是不用的,因为它们只在add.c里面的一个函数里能用。

比如:
test.o的符号表

符号地址
Add0x00
main0x19

add.o的符号表

符号地址
Add0xff

注意:

  • 我们test.o所对应的Add符号的地址,是无效地址,为什么:因为在test.c里面我们根本没有定义Add这个函数所以无效,而add.o里面那个才是有效的。

那么我们如何去演示呢?
首先.o文件我们肯定是看不懂的,因为这个文件的格式其实是叫做elf格式,Linux上有一个工具叫做readelf可以帮我们翻译这个.o文件。

里面有很多选项可以看,我们看符号表就行了


对比两个符号表:

形成符号表之后,我们编译这个环节,就完成了,cl.exe(编译器)的使命就完成了。
那么符号表到底有啥用呢?接下来,到了链接环节。

链接

链接

  1. 合并段表
  2. 符号表的合并和重定位

合并段表:就是把相同的东西合并在一起。 这个过程博主不详细给大家讲解了。
接下来我们来详细说说,符号表的合并和重定位。

我们来看看上一阶段我们生成的两个符号表:

我们要将其合并。
合并的意思就是,我们来找相同的符号。
比如Add符号,链接器找到两个Add。这时,链接器会发现,有一个Add的地址是有效的,有一个是无效的,此时链接器会丢弃无效的那个地址,保留有效的地址。

其实简单来说就是把源文件弄在一起了。

那么我们懂得这个知识之后,我们就可以知道我们平时在学习过程中常见的错误是什么意思了。

  • 如果我们将刚才的add.c里面的内容删掉,或者把Add函数改个名字,这样我们在合并符号表的时候,test.c里面那个Add是无效的,这时,链接器就会去表里找,找有效的Add,找不到,就会报错了,这个错误就是链接错误!



这样我们就能很好地理解这个错误是怎么报出来的了。
成功生成目标文件之后,链接期间,找不到Add了—报链接错误。

运行环境

程序执行的过程:

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

尾声

如果对预编译(预处理)这个过程感兴趣的伙伴,可以通过博主提供 的传送门食用。【预定义】C语言预定义代码(宏、条件编译等)内容介绍【最全的保姆级别教程】
看到这里,相信大家已经对程序的编译,运行等过程有了比较深入的了解了,其实学习这些对我们写代码能力的帮助其实是不大的,但是这些都是内功的修炼,都是硬核知识,在我们找工作,或者在完成项目时,这种深入的理解对我们的帮助是非常大的。
如果你觉得这篇文章对你有帮助的话,不要忘了一键三连后再离开噢!

有关【C语言深度解剖】一篇解决程序的环境【编译+链接详解】让面试官给我们竖起大拇指的更多相关文章

  1. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  2. ruby - 寻找通过阅读代码确定编程语言的ruby gem? - 2

    几个月前,我读了一篇关于ruby​​gem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:

  3. ruby-on-rails - Ruby url 到 html 链接转换 - 2

    我正在使用Rails构建一个简单的聊天应用程序。当用户输入url时,我希望将其输出为html链接(即“url”)。我想知道在Ruby中是否有任何库或众所周知的方法可以做到这一点。如果没有,我有一些不错的正则表达式示例代码可以使用... 最佳答案 查看auto_linkRails提供的辅助方法。这会将所有URL和电子邮件地址变成可点击的链接(htmlanchor标记)。这是文档中的代码示例。auto_link("Gotohttp://www.rubyonrails.organdsayhellotodavid@loudthinking.

  4. ruby-on-rails - Prawn - 表格单元格内的链接 - 2

    我正在尝试用Prawn生成PDF。在我的PDF模板中,我有带单元格的表格。在其中一个单元格中,我有一个电子邮件地址:cell_email=pdf.make_cell(:content=>booking.user_email,:border_width=>0)我想让电子邮件链接到“mailto”链接。我知道我可以这样链接:pdf.formatted_text([{:text=>booking.user_email,:link=>"mailto:#{booking.user_email}"}])但是将这两行组合起来(将格式化文本作为内容)不起作用:cell_email=pdf.make_c

  5. Unity 热更新技术 | (三) Lua语言基本介绍及下载安装 - 2

    ?博客主页:https://xiaoy.blog.csdn.net?本文由呆呆敲代码的小Y原创,首发于CSDN??学习专栏推荐:Unity系统学习专栏?游戏制作专栏推荐:游戏制作?Unity实战100例专栏推荐:Unity实战100例教程?欢迎点赞?收藏⭐留言?如有错误敬请指正!?未来很长,值得我们全力奔赴更美好的生活✨------------------❤️分割线❤️-------------------------

  6. 【Java 面试合集】HashMap中为什么引入红黑树,而不是AVL树呢 - 2

    HashMap中为什么引入红黑树,而不是AVL树呢1.概述开始学习这个知识点之前我们需要知道,在JDK1.8以及之前,针对HashMap有什么不同。JDK1.7的时候,HashMap的底层实现是数组+链表JDK1.8的时候,HashMap的底层实现是数组+链表+红黑树我们要思考一个问题,为什么要从链表转为红黑树呢。首先先让我们了解下链表有什么不好???2.链表上述的截图其实就是链表的结构,我们来看下链表的增删改查的时间复杂度增:因为链表不是线性结构,所以每次添加的时候,只需要移动一个节点,所以可以理解为复杂度是N(1)删:算法时间复杂度跟增保持一致查:既然是非线性结构,所以查询某一个节点的时候

  7. 7个大一C语言必学的程序 / C语言经典代码大全 - 2

    嗨~大家好,这里是可莉!今天给大家带来的是7个C语言的经典基础代码~那一起往下看下去把【程序一】打印100到200之间的素数#includeintmain(){ inti; for(i=100;i 【程序二】输出乘法口诀表#includeintmain(){inti;for(i=1;i 【程序三】判断1000年---2000年之间的闰年#includeintmain(){intyear;for(year=1000;year 【程序四】给定两个整形变量的值,将两个值的内容进行交换。这里提供两种方法来进行交换,第一种为创建临时变量来进行交换,第二种是不创建临时变量而直接进行交换。1.创建临时变量来

  8. 深度学习部署:Windows安装pycocotools报错解决方法 - 2

    深度学习部署:Windows安装pycocotools报错解决方法1.pycocotools库的简介2.pycocotools安装的坑3.解决办法更多Ai资讯:公主号AiCharm本系列是作者在跑一些深度学习实例时,遇到的各种各样的问题及解决办法,希望能够帮助到大家。ERROR:Commanderroredoutwithexitstatus1:'D:\Anaconda3\python.exe'-u-c'importsys,setuptools,tokenize;sys.argv[0]='"'"'C:\\Users\\46653\\AppData\\Local\\Temp\\pip-instal

  9. ruby - 使用 Watir 检查错误链接 - 2

    我有一个未排序的链接列表,我将其保存在旁边,我想单击每个链接并确保它转到真实页面而不是404、500等。问题是我不知道该怎么做。是否有一些我可以检查的对象会给我http状态代码或任何东西?mylinks=Browser.ul(:id,'my_ul_id').linksmylinks.eachdo|link|link.click#needtocheckfora200statusorsomethinghere!how?Browser.backend 最佳答案 我的回答与铁皮人的想法类似。require'net/http'require'

  10. ruby - 如何为 pbcopy 生成富文本链接 - 2

    我一直在玩一个脚本,它在Chrome中获取选定的文本并在Google中查找它,提供四个最佳选择,然后粘贴相关链接。它以不同的格式粘贴,具体取决于当前在Chrome中打开的页面-DokuWiki打开的DokuWiki格式,普通网站的HTML,我想要我的WordPress所见即所得编辑器的富文本。我尝试使用pbpaste-Preferrtf来查看没有其他样式的富文本链接在粘贴板上的样子,但它仍然输出纯文本。在文本编辑中保存文件并进行试验后,我想出了以下内容text=%q|{\rtf1{\field{\*\fldinst{HYPERLINK"URL"}}{\fldrsltTEXT}}}|te

随机推荐