插播!插播!插播!亲爱的朋友们,我们的Makefile课程上线啦!感兴趣的小伙伴可以去下面的链接学习哦~
https://edu.csdn.net/course/detail/39264
从最简单的一个程序helloworld.c程序说起,
#include <stdio.h>
int main()
{
printf("Hello World.\n");
return 0;
}
它的生命周期是从一个源程序开始的,即通过编辑器创建并保存的文本文件。源程序实际上就是一个由0和1组成的位序列,8个位被组织成一组称为字节,每个字节表示程序中的某些文本字符。
helloworld.c的表示方法说明了一个基本思想:系统中所有的信息---包括磁盘文件,内存中的程序,内存中存放的用户数据以及网络上传送的数据,都是由一串位序列(比特)表示的。
1. 编译过程
helloworld.c程序是从一个高级C程序开始的,为了在系统上运行此程序,每条C语言都必须被其他程序转化为一系列的低级机器语言指令,然后这些指令按照一种称为可执行目标程序的格式打包,并以二进制磁盘文件的形式存放起来。
编译器读取源程序文件helloworld.c,并把它翻译成一个可执行文件helloworld,这个翻译过程可分为四个阶段完成。执行这四个阶段的程序:预处理器,编译器,汇编器和链接器,一起构成了编译系统。
2.预处理阶段
预处理器根据以字符#开头的命令,修改原始的C程序,比如#include<stdio.h>命令告诉预处理器读取系统头文件stdio.h的内容,并把它直接插入程序文本中,结果就得到了另一个C程序,通常是以.i作为文件扩展名。
gcc -E helloworld.c -o helloworld.i
-E 选项告诉编译器只进行预处理操作
-o 选项把预处理的结果输出到指定文件
3.编译阶段
编译器将文本helloworld.i翻译成文本文件helloworld.s,它包含一个汇编语言程序。该程序包含函数main的定义,每条语句都以一种文本格式描述了一条低级机器语言指令。汇编语言非常有用,它为不同高级语言的不同编译器提供了通用的输出语言。
gcc -S helloworld.c -o helloworld.s
-S 选项告诉编译器,进行预处理和编译成汇编语言操作
4.汇编阶段
汇编器将helloworld.s翻译成机器语言指令,把这些指令打包成一种可重定位目标程序的格式,并将结果保存在目标文件helloworld.o中。helloworld.o文件是一个二进制文件,它包含的17个字节是函数main的指令编码,如果打开helloworld.o文件,将看到乱码。
gcc -c helloworld.c -o helloworld.o
5.链接阶段
将.o文件和库文件链接成为可被操作系统执行的可执行程序,例如helloworld程序调用了printf函数,它是每个C编译器都提供的标准C库中的一个函数,printf函数存在于一个名为printf.o的单独的预编译好的目标文件中,而这个文件必须以某种方式合并到我们的helloworld.o程序中。链接器就负责处理这种合并,结果就得到helloworld文件,它是一个可执行目标文件,可以被加载到内存中,由系统执行。
gcc helloworld.c -o helloworld
执行程序
./helloworld
默认情况下,make会在工作目录(执行make的目录)下按照文件名顺序寻找makefile文件读取并执行,查找的文件名顺序为:“GNUmakefile”、“makefile”、“Makefile”。通常应该使用“makefile”或者“Makefile”作为一个makefile的文件名,“GNUmakefile”是我们不推荐使用的文件名,因为以此命名的文件只有“GNU make”才可以识别,而其他版本的make程序只会在工作目录下“makefile”和“Makefile”这两个文件。