版权声明:欢迎转载,互相学习。 https://blog.csdn.net/SmalOSnail/article/details/53208867

一个C语言程序从源代码变为最后的可执行文件,需要经历预处理、编译、汇编、链接这四个过程。

  这是一般C语言入门书籍上面会提到的,但是很少有人入门时关注这一点,照着书上的代码直接开始码”Hello World.c”。而现在的编译器一般是一步到位,如Dev-cpp,只需要点一下“编译”就可以把源代码直接变成可执行文件。这样做虽然节约了时间,却不利于新手们从底层开始学习C语言。甚至可能学到最后连什么是预处理、汇编、链接都不清楚,对程序编译的过程没有什么感觉。
  
  在这篇文章中,大家可以通过自己动手实践,逐步地理解、感受c语言的编译过程。

  本文使用linux操作环境,windows用户可以安装linux虚拟机或者下载linux模拟器,或者尝试微软的实验功能——linux子系统

  • 虚拟机安装教程:
    http://wiki.ubuntu.com.cn/虚拟机中安装Ubuntu
  • 模拟器下载地址:
    http://mingw.org/
  • linux子系统安装:
    https://linux.cn/article-7209-1.html

文中主要使用gcc命令以及以下几个参数:

  -E          Preprocess only; do not compile, assemble or link-S          Compile only; do not assemble or link-c          Compile and assemble, but do not link-o <file>   Place the output into <file>

环境配置好以后,让我们开始c语言的编译之旅吧~

编写c语言源代码

很多linux命令都可以新建一个文件,比如

$ touch test.c

建立一个空白的文件

$ vim test.c

使用vim(文本编辑器)编辑test.c,如果test.c不存在,则创建

$ echo "123" > test.c

通过输出重定向新建一个文件

创建完test.c后,将下面这段Hello World代码写到test.c中(很多方法)

#include <stdio.h>
int main(){printf("Hello world\n");return 0;
}

写完之后可以使用ls命令来查看当前目录下的文件,检查test.c是否存在

$ ls

使用cat命令查看test.c中的内容,检查是否写入成功

$ cat test.c

展开头文件(预处理)

$ gcc -E test.c -o test_pre.c

这个命令把源代码test.c中的头文件展开,并把结果输出到test_pre.c

(可以使用cat或者vim命令查看test_pre.c文件中的内容)

test_pre.c中的内容是这样的,可以发现原本几行的代码变成了几百行,而且已经见不到include关键字了,取而代之的是一些变量定义的代码,这些代码就是stdio.h中的内容,和stdio.h中头文件展开后的内容。

编译

$ gcc -S test_pre.c -o test_asm.s

这一条命令将上一步预处理过后的源代码编译成为汇编代码


现在看到的是test_asm.s里面的汇编代码。

什么是汇编?

汇编语言是汇编指令集、伪指令集和使用它们规则的统称,使用具有一定含义的符号为助忆符,用指令助忆符、符号地址等组成的符号指令称为汇编格式指令。

简单的可以理解为汇编语言是一本词典,01100101011010这样的二进制字符串是单词,汇编指令是单词的含义。计算机能读懂二进制字符串,而人能读懂的是翻译过来的汇编指令。

汇编

$ gcc -c test_asm.s -o test_obj.o

这一步将test_asm.s汇编成为目标文件,目标文件中存储的就是010101010这样的字符串了,可以用cat命令试试去读取test_obj.o

可以发现打印出来许多不可见的字符,原因是目标文件已经是二进制格式的了,不同于源代码(文本格式)

有关文件的格式可以看下这里的介绍:
http://www.cnblogs.com/zhangjiankun/archive/2011/11/27/2265184.html

链接

链接器负责将程序的目标文件与所需的所有附加的目标文件连接起来,最终生成可执行文件。附加的目标文件包括静态连接库和动态连接库。
  • 1

这个例子中没有附加的目标文件,所以只需要目标文件做被链接的对象。

有关链接器的详细讲解大家可以看下这里:
https://www.zhihu.com/question/27386057

$ gcc test_obj.o -o hello

gcc本身可以充当链接器,这里使用gcc命令将目标文件test_obj.o链接成了可执行文件hello

运行程序!

至此,源代码已经经历了预处理、编译、汇编、链接四步成为了可执行文件,现在试着运行一下这个程序吧

$ ./hello

小结

  首先我们创建了源文件test.c,然后用gcc -E将源文件中的头文件展开,这一步叫做预处理;
  之后通过gcc -S将预处理后的源文件编译了汇编代码,这一步叫做编译;
  接着使用gcc -c命令将汇编代码转换成了二进制的目标文件,这一步操作叫做汇编;
  目标文件不同于源代码,是二进制格式,是源文件编译过程中产生的中间文件,通过链接器可以将多个目标文件链接成为可执行文件,这一步叫做链接

源文件->(预处理->编译->汇编->链接)->可执行文件

  一般大家所说的c语言编译,其实是上述这四步的简称。

通过简单的Linux命令,编译一个C语言代码相关推荐

  1. 一份简单的在 Linux下编译及调试 C 代码的指南

    摘要: 一份简单的在 Linux下编译及调试 C 代码的指南 对于Linux下的C程序员来说,几乎天天都会和Linux打交道.但在很多人的眼中,Linux是一个易用性极差.靠命令驱动的操作系统,根本无 ...

  2. 编译我的第一个c语言,linux菜鸟学习写第一个C语言代码--“hello Linux!”

    2004年4月20日最新版本的GCC编译器3.4.0发布了.目前,GCC可以用来编译C/C++.FORTRAN.JAVA.OBJC.ADA等语言的程序,可根据需要选择安装支持的语言.GCC 3.4.0 ...

  3. 手把手教你如下在Linux下如何写一个C语言代码,编译并运行

    文章目录 手把手教你如下在Linux下如何写一个C语言代码,编译并运行 打开Ubuntu终端 创建 helloworld.c 编译C文件 手把手教你如下在Linux下如何写一个C语言代码,编译并运行 ...

  4. 在vmware中安装centos并使用gcc执行第一个c语言代码

    目录 1.安装虚拟机VMWare 2.下载镜像文件(这里使用的是centos7) 3.如果你之前centos不想要了,请按照下面图片进行删除 4.打开VMWare创建配置虚拟机 5.配置安装CentO ...

  5. Linux内核编译很简单,6步编译一个自己的内核

    考虑离开在前面文章中我们反复提到过Linux内核,知道Linux内核才是Linux操作系统最为核心的内容.内核实现了对硬件的管理,为应用软件提供了使用硬件的接口. 对于Linux开发人员而言,内核的学 ...

  6. 一个简单的linux命令——ls

    linux命令之–ls 一.命令详解 -a, –all 列出目录下的所有文件,包括以 . 开头的隐含文件 -A 同-a,但不列出"."(表示当前目录)和".." ...

  7. 用 Linux 命令玩一个有趣的数学游戏

    在家玩流行的英国游戏节目 "Countdown" 中的数字游戏. 像许多人一样,我在大流行期间看了不少新的电视节目.我最近发现了一个英国的游戏节目,叫做 Countdown,参赛者 ...

  8. linux命令编写,编写简单的linux命令

    8种机械键盘轴体对比 本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选? 又到了周四分享环节,鉴于最近在看linux编程实践,所以就的讲一下如何编写一个简单的who命令. PPT Manual ...

  9. linux命令编译C语言程序

    C语言简介: BCPL->newB->C->UNIX->Linux->gcc C语言专门编写操作系统的语言,所以天生适合对硬件编程,也以运行速度快著称,也非常适合实现数据 ...

最新文章

  1. 【迁移2018-04-12 10:46:11】BeanCopier之MapStruct(一)
  2. 【数据可视化应用】绘制峰峦地图(附Python和R语言代码)
  3. Python教程:推荐一个比 open 读文件还好用、方便的库
  4. lbp特征提取算法 知乎_计算机视觉基础-图像处理: LBP特征描述算子
  5. 关于ttk的使用与安装
  6. 君子动手不动口,阿里云喊你做云上体验官啦!
  7. cdh hive on spark_Flink 与 Hive 的磨合期
  8. np.unique()官方文档分析以及举例
  9. SpringBoot 手写过滤器amp;加载第三方过滤器
  10. Python 3. 里filter与generator expression的区别
  11. SQL Server存储过程中使用表值作为输入参数示例
  12. PHP模拟实现url rewrite
  13. 5款优秀的在线表单设计器
  14. Vertical roller mill lead blast furnace slag processing equipment
  15. 失焦事件触发_js中表单的聚焦失焦事件
  16. C++Primer 第10章 bind与迭代器
  17. 子线程何时开启、何时结束
  18. 回归分析中的p值和R方哪个更重要?
  19. 一文掌握APQP(产品质量策划)
  20. matlab的sinxx,用MATLAB程序编程:分析方程f(x)=sinx-x/2=0正根的分布情况,并用二分法求正根近似值,使误差不超过0.01....

热门文章

  1. js如何判断一个对象是不是Array
  2. undo自动调优介绍
  3. [基础题] 7.第二种(*)按如下要求编写Java程序:
  4. 计算机系统NSX,2017款的讴歌NSX计算机维持的“战斗机”
  5. 陕西国防 c语言第三章实训三答案,C语言程序设计(上)
  6. 一入爬虫深似海,反爬技术你知多少?
  7. 【Linux网络编程】循环服务器之UDP循环模型
  8. 【Linux】一步一步学Linux——fc命令(224)
  9. 【Linux】一步一步学Linux——ipcalc命令(191)
  10. 【cJSON】CJSON学习笔记(二)