计算机中所有的文件都是以01数字形式保存的,我们常见的程序文件也是如此,以常见的入门程序Hello.c为例,其代码为代码段1所示:

代码段1

//hello.c
#include <stdio.h>
int main()
{
printf("hello, world\n");
}

机器中所有的字符都是用数字进行表示,可以按照ascii码表对比一下,将该Hello.c文件中每个字符用ascii代码表示,如下所示:

在文件中存储的都是绿色行表示的数字,当然,在实际的存储过程还不是这些十进制数字,而是’0’、’1’.

上述Hello.c文件需要经过以下几个步骤才能变成可执行文件,这是一种特殊的能被机器识别并执行的文件。

为什么可执行文件能被机器识别并运行,而其他的文件例如上面的Hello.c或者自己定义的world文档、txt文档就不能被机器识别呢?

简而言之,可以认为这些可执行文件是按照机器能够识别的格式进行存储的。以说话为例,假如张三会说汉语和日语,如果你对着他说英语或韩语,他也就听不懂了。这种特殊的可执行文件的格式一般都是COFF(common file format)格式,该格式在不同操作系统下具体的实现方式还是不一样的,例如linux系统下可执行文件就是ELF文件格式,Windows下面的可执行文件exe就是PE文件格式(例如main.exe),这两种格式都COFF文件格式的变种。

程序的编译过程大致要经过图1 所示的步骤之后才能变成一个可以被机器直接识别和执行的“可执行文件”。

图1、编译过程

编译过程是以源文件为单位进行的,头文件不会单独编译而是放在包含它的头文件中一起编译。例如代码段2总共有“test.h”、“test.c”、“main.c”三个文件,在编译的时候,编译器将对源文件“test.c”和“main.c”进行编译,而头文件“test.h”将不会被作为编译单元进行编译。

代码段2

//test.h
int add(int iNum1, int iNum2);
//test.c
#include "test.h"
int add(int iNum1, int iNum2)
{
return iNum1 + iNum2;
}
//main.c
#include <stdio.h>
#include "test.h"
#define NUM1 10
#define NUM2 20
int main()
{
int iRes =0;
iRes = add(NUM1,NUM2);
printf("NUM1+NUM2=%d",iRes);
}

1、预处理,该过程主要将一些头文件(例如test.c中的test.h文件)、宏定义之类的替换过来,也即,如果你包含了哪些头文件就把那些头文件拷贝过来,因此经过这一步处理之后,test.h就被复制到了文件“test.c”和“main.c”中,同时“main.c”中define的两个宏NUM1和NUM2也被替换成所表示的数字10和20;如果程序中当然程序中的注释也会在这一步被去掉,所以程序中适当的加入注释并不会影响程序的性能也最终生成可执行文件的大小的。以linux为例,使用下面两条命令:

gcc –E test.c –o test.i

gcc –E main.c –o main.i

就会将“test.c”和“main.c”进行预处理,然后生成“test.i”和“main.i”两个文件,这两个文件。

2、编译,该过程主要对源文件进行一系列的处理,例如词法分析、语法分析、语义分析和优化等,也就是编译原理课程上面讲述的那些步骤,经过这些步骤之后,每一个编译单元都对应生成了一个汇编文件。在linux下,使用如下两个命令:

gcc –S test.i –o test.s

gcc –S main.i –o main.s

可将预处理之后的.i文件生成对应的汇编文件。

3、汇编,该过程主要是将编译生成的汇编文件翻译成机器码,由于每个汇编命令就对应一个特定的机器指令,因此只需要将汇编文件中的汇编质量替换成机器指令就可以了。在linux下,使用如下两个命令:

gcc –c test.s –o test.o

gcc –c main.s –o main.o

可将编译过程生成的汇编文件生成目标文件。

4、链接,理论上将,如果不依赖于外部的东西,经过汇编之后的目标文件里就是机器可以识别的机器码了。再回头看看生成的“test.o”和“main.o”两个目标文件,由于我们在“main.c”文件中使用了函数add,在编译的时候也包含了对应的头文件“test.h”,但是add函数是在另一个编译单元“test.c”中定义的,在机器执行main函数中调用add函数时就需要知道add的地址在哪里?这是就需要连接器了,连接器会搜索所有的编译单元生成的目标文件,看看这个add函数在哪个目标文件里,找到之后就将add函数的地址填在调用它的地方。这样程序在调用add的时候就知道去哪里找它了。

参考《深入理解计算机系统》、《程序员的自我修养——动态链接、装载和库》

从helloworld回顾程序的编译过程之一相关推荐

  1. 从helloworld回顾程序的编译过程之三——静态链接

    本文关于静态链接库的链接过程分析是对<程序员的自我修养--链接.装载与库>这本书的一点学习总结,另外,本文是在linux操作系统下进行验证和测试,所使用的测试文件为:main.c和add. ...

  2. 从helloworld回顾程序的编译过程之二

    为简单起见,本文中的例子将不使用printf之类的标准库函数,文中只使用自己定义的函数,下面的例子中主要是在linux环境下进行验证和调试的,如果没有linux开发环境也不要紧,本文已经将在linux ...

  3. gcc编译c文件_Linux下C语言程序的编译过程

    Linux下C语言程序的编译过程 使用gcc编译程序时,编译工程分为4个阶段: (1)预处理:(Pre-Processing) (2)编译:(Compiling) (3)汇编:(Assembling) ...

  4. WPF 程序的编译过程

    基于 Sdk 的项目进行编译的时候,会使用 Sdk 中附带的 props 文件和 targets 文件对项目进行编译.Microsoft.NET.Sdk.WindowsDesktop 的 Sdk 包含 ...

  5. 五分钟带你了解!Java程序的编译过程

    Java程序的编译过程 Java 语言的「编译期」其实是一段「不确定」的操作过程.因为它可能是一个前端编译器(如 Javac)把 *.java 文件编译成 *.class 文件的过程:也可能是程序运行 ...

  6. C语言程序makefile编译过程

    C语言程序makefile编译过程 2022-0111 blog_010 makefile是一些大型linux下开发的项目经常会用到的编译脚本: 可以将makefile理解为类似shell一样的脚本语 ...

  7. 开发日记-20190903 关键词 C程序gcc编译过程

    感觉挺茫然的,很多大学期间应该知道的事情,直到工作了一年了,自己才渐渐地意识到自己想要知道,要是大学期间能有人能帮助我,或许我,真的不会这么茫然吧,真的,真的.不过我也知道后悔过去,是一件多么愚蠢的事 ...

  8. 理解C语言(零) 导读(上):C程序的编译过程- 机器级表示

    1 从Hello world说起 Hello world是初学者使用任何一项编程语言最基本最简单的程序.下面是一个C语言版的"Helloworld" : #include < ...

  9. 【嵌入式开发】gcc 学习笔记(一) - 编译C程序 及 编译过程

    一. C程序编译过程 编译过程简介 : C语言的源文件 编译成 可执行文件需要四个步骤, 预处理 (Preprocessing) 扩展宏, 编译 (compilation) 得到汇编语言, 汇编 (a ...

最新文章

  1. C# using 语法说明
  2. C语言模拟实现(一)----- 优先权抢占式时间片调度算法
  3. hdu 5093 二分匹配
  4. 路由技术(来自百度百科)
  5. LinuxCentos7 防火墙开放端口,查看状态,查看开放端口
  6. Wi-Fi 联盟撤销华为资格;华为已熟练掌握 ARM 架构修改;苹果 2020 年或推 5G 手机 | 极客头条...
  7. 【MapGIS精品教程】002:GDB本地数据库的使用
  8. uboot之uboot中环境变量
  9. kafka-Streaming错误:在IDEA连接kafka时出现错误
  10. 计算机网络技术基础竞赛题,网络技术基础知识竞赛试题
  11. 荒野行动电脑版一直连接服务器,荒野行动PC版进不去怎么办 电脑版连接不上服务器的解决方法...
  12. 离散数学学习笔记——命题逻辑
  13. 计算机三级网络技术最全知识点总结【5】
  14. 什么是DHCP?为什么要用DHCP?(中科三方)
  15. 2020年日历电子版(打印版)_2020年日历表(竖版-A4纸打印版)
  16. 点开计算机桌面选项怎么不见了,电脑桌面开始菜单不见了应该如何解决?_开始菜单不见了解决办法介绍...
  17. 网吹钱伟长写论文“不必参考任何文献”,但这的确不符合学术规范
  18. 软件设计师考试注意事项
  19. AI测试:让软件测试变得聪明伶俐
  20. 2022年度中国科学十大进展:8所高校科研成果脱颖而出,深圳大学入选!

热门文章

  1. python3 模板库_[zz]尝试PyTenjin --号称最快的Python 模板库
  2. angular监听输入框值的变化_如何检测Angular中@Input()值何时发生变化?
  3. hashmap put复杂度_集合类HashMap,HashTable,ConcurrentHashMap区别?
  4. flume数据采集_大数据采集系统Flume集群部署
  5. wcf html 界面,WCF数据转换为原始html而不是Json格式
  6. 语言程序推箱子课设报告_“延期不延学”第13期 | C++篇 | c++课设建议
  7. python常用的库_这几个常用的python库你需要知道
  8. icon 做成html形式,一段生成iconfont预览html的代码
  9. 口红会染唇是什么意思_别只知道露华浓了!这些平价口红,我吹爆!
  10. java正则表达式笔记_java正则表达式笔记