C语言编译和链接详解(通俗易懂,深入本质)
2年前 (2024-04-27)
我们平时所说的程序,是指双击后就可以直接运行的程序,这样的程序被称为可执行程序(Executable Program)。在 Windows 下,可执行程序的后缀有
可执行程序的内部是一系列计算机指令和数据的,它们都是二进制形式的,CPU 可以直接识别,毫无障碍;但是对于程序员,它们非常晦涩,难以记忆和使用。

你感受一下,直接使用二进制是不是想撞墙,是不是受到一吨重的伤害?
编译器能够识别代码中的词汇、句子以及各种特定的格式,并将他们转换成计算机能够识别的二进制形式,这个过程称为编译(Compile)。
你的代码语确与否,编译器说了才算,我们学习C语言,从某种意义上说就是学习如何使用编译器。
编译器可以 保证你的代码从语法上讲是正确的,因为哪怕有一点小小的错误,编译也不能通过,编译器会告诉你哪里错了,便于你的更改。
目标文件经过链接(Link)以后才能变成可执行文件。既然目标文件和可执行文件的格式是一样的,为什么还要再链接一次呢,直接作为可执行文件不行吗?
不行的!因为编译只是将我们自己写的代码变成了二进制形式,它还需要和系统组件(比如标准库、动态链接库等)结起来,这些组件都是程序运行所必须的。
链接(Link)其实就是一个“打包”的过程,它将所有二进制形式的目标文件和系统组件组成一个可执行文件。完成链接的过程也需要一个特殊的软件,叫做链接器(Linker)。
随着我们学习的深入,我们编写的代码越来越多,最终需要将它们分散到多个源文件中,编译器每次只能编译一个源文件,生成一个目标文件,这个时候,链接器除了将目标文件和系统组件组起来,还需要将编译器生成的多个目标文件组起来。
.exe和.com(其中.exe比较常见);在类 UNIX 系统(Linux、Mac OS 等)下,可执行程序没有特定的后缀,系统根据文件的头部信息来判断是否是可执行程序。可执行程序的内部是一系列计算机指令和数据的,它们都是二进制形式的,CPU 可以直接识别,毫无障碍;但是对于程序员,它们非常晦涩,难以记忆和使用。
例如,在屏幕上输出“VIP会员”,C语言的写法为:
puts("VIP会员");
二进制的写法为:
你感受一下,直接使用二进制是不是想撞墙,是不是受到一吨重的伤害?
直接使用二进制指令编程对程序员来说简直是噩梦,尤其是当程序比较大的时候,不但编写麻烦,需要频繁查询指令手册,而且除错会异常苦恼,要直接面对一堆二进制数据,让人眼花缭乱。另外,用二进制指令编程步骤繁琐,要考虑各种边界情况和底层问题,开发效率十分低下。在计算机发展的初期,程序员就是使用这样的二进制指令来编写程序的,那个拓荒的年代还没有编程语言。
这就倒逼程序员开发出了编程语言,提高自己的生产力,例如汇编、C语言、C++、Java、Python、Go语言等,都是在逐步提高开发效率。此,编程终于不再是只有极客能做的事情了,不了解计算机的读者经过一定的训练也可以编写出有模有样的程序。
编译(Compile)
C语言代码由固定的词汇按照固定的格式组织起来,简单直观,程序员容易识别和理解,但是对于CPU,C语言代码就是天书,根本不认识,CPU只认识几百个二进制形式的指令。这就需要一个工具,将C语言代码转换成CPU能够识别的二进制指令,也就是将代码加工成 .exe 程序的格式;这个工具是一个特殊的软件,叫做编译器(Compiler)。编译器能够识别代码中的词汇、句子以及各种特定的格式,并将他们转换成计算机能够识别的二进制形式,这个过程称为编译(Compile)。
编译也可以理解为“翻译”,类似于将中文翻译成英文、将英文翻译成象形文字,它是一个复杂的过程,大致包括词法分析、语法分析、语义分析、性能优化、生成可执行文件五个步骤,期间涉及到复杂的算法和硬件架构。对于学计算机或者软件的大学生,“编译原理”是一门专业课程,有兴趣的读者请自行阅读《编译原理》一书,这里我们不再展开讲解。
注意:不了解编译原理并不影响我们学习C语言,我也不建议初学者去钻研编译原理,贪多嚼不烂,不要把自己绕进去。
C语言的编译器有很多种,不同的平台下有不同的编译器,例如:
- Windows 下常用的是微软开发的 Visual C++,它被集成在 Visual Studio 中,一般不单独使用;
- Linux 下常用的是 GUN 组织开发的 GCC,很多 Linux 发行版都自带 GCC;
- Mac 下常用的是 LLVM/Clang,它被集成在 Xcode 中(Xcode 以前集成的是 GCC,后来由于 GCC 的不配才改为 LLVM/Clang,LLVM/Clang 的性能比 GCC 更加强大)。
你的代码语确与否,编译器说了才算,我们学习C语言,从某种意义上说就是学习如何使用编译器。
编译器可以 保证你的代码从语法上讲是正确的,因为哪怕有一点小小的错误,编译也不能通过,编译器会告诉你哪里错了,便于你的更改。
链接(Link)
C语言代码经过编译以后,并没有生成最终的可执行文件(.exe 文件),而是生成了一种叫做目标文件(Object File)的中间文件(或者说临时文件)。目标文件也是二进制形式的,它和可执行文件的格式是一样的。对于 Visual C++,目标文件的后缀是.obj;对于 GCC,目标文件的后缀是.o。目标文件经过链接(Link)以后才能变成可执行文件。既然目标文件和可执行文件的格式是一样的,为什么还要再链接一次呢,直接作为可执行文件不行吗?
不行的!因为编译只是将我们自己写的代码变成了二进制形式,它还需要和系统组件(比如标准库、动态链接库等)结起来,这些组件都是程序运行所必须的。
链接(Link)其实就是一个“打包”的过程,它将所有二进制形式的目标文件和系统组件组成一个可执行文件。完成链接的过程也需要一个特殊的软件,叫做链接器(Linker)。
随着我们学习的深入,我们编写的代码越来越多,最终需要将它们分散到多个源文件中,编译器每次只能编译一个源文件,生成一个目标文件,这个时候,链接器除了将目标文件和系统组件组起来,还需要将编译器生成的多个目标文件组起来。
再次强调,编译是针对一个源文件的,有多少个源文件就需要编译多少次,就会生成多少个目标文件。
总结
不管我们编写的代码有多么简单,都必须经过「编译 --> 链接」的过程才能生成可执行文件:
编译就是将我们编写的源代码“翻译”成计算机可以识别的二进制格式,它们以目标文件的形式存在;
链接就是一个“打包”的过程,它将所有的目标文件以及系统组件组成一个可执行文件。
如果不是特别强调,一般情况下我们所说的“编译器”实际上也包括了链接器,比如,你使用了哪种编译器?去哪里下载C语言编译器?我的编译器为什么报错了呢?
- 随机文章
- 亚 马尔代夫(重写后的标题:探索壮观亚马尔代夫:天堂之岛旅程)
- 现在 能去 马尔代夫(如何计划前往美丽的马尔代夫旅行?)
- 印尼马尔代夫海啸(印尼和马尔代夫遭遇海啸,数百人失踪)
- 普吉 巴厘 马尔代夫(三地旅游说走就走!普吉、巴厘、马尔代夫等你来体验!)
- 马尔代夫葫芦(探秘马尔代夫奇特的海底世界)
- 国际轻奢马尔代夫(马尔代夫:全球最奢华岛国的心动体验)
- 小野解说马尔代夫(小野带你游马尔代夫,感受海岛之美!)
- 东方马尔代夫项目(东方集团在马尔代夫启动高端旅游项目)
- 屯留马尔代夫溺水(马尔代夫游客溺水身亡,提醒安全警示)
- 新航 马尔代夫(新加坡航空开通马尔代夫航线)
- 昌平马尔代夫酒店(昌平维景马尔代夫酒店:奢华度假胜地)
- 泰国马尔代夫国家(泰国游客热捧马尔代夫,成为旅游新宠)
- 晚上马尔代夫派对(晚上的马尔代夫:派对狂欢的海滨之夜)
- 星空帐篷马尔代夫(在马尔代夫星空下露营体验:星空帐篷)
- 深圳马尔代夫介绍(探索深圳马尔代夫身临其境的度假天堂)
- 自驾游到马尔代夫(从自驾游到马尔代夫——探索热带风情)
- 青建 马尔代夫(青建承建的马尔代夫工程完美收官)
- 赶海马尔代夫图片(惊艳海底世界!探索马尔代夫海洋奇观)
- 美居 马尔代夫(美居入住马尔代夫:享受浪漫度假!)
- 柏典马尔代夫饮食(柏典马尔代夫美食:品尝引领心灵独白)
- 蕲春蕲州马尔代夫(蕲州公务员在马尔代夫旅游遭强制隔离)
- 选岛 马尔代夫(探秘马尔代夫:美丽岛屿等你来发现!)
- 马尔代夫中国青海(青海助力马尔代夫发展,共建中马友谊)
- 美爵 马尔代夫(美爵度假酒店:奢华浪漫的马尔代夫之旅)
- 大疆 马尔代夫(大疆携手马尔代夫:空中拍摄开启海底奇观之旅)
- 马尔代夫军队编制(马尔代夫军队宣布完成新一轮编制改革)
- 道具 马尔代夫(探秘马尔代夫隐藏版,揭秘未被游客发掘的神秘景点!)
- 晓宇 马尔代夫(【美丽马尔代夫】晓宇为你详细解读马尔代夫的美丽与魅力)
- 马尔代夫债务暂缓(马尔代夫成功和解债务,暂缓得以实现)
- 饶平马尔代夫图片(惊艳海底世界!精美饶平马尔代夫游记)
