文章目录
- 分布编译
- 预处理
- 编译
- 汇编
- 链接
- 注释
- 单行注释
- 多行注释
- 预处理注释
- 总结
分布编译
上一节使用 gcc main.c就生成了a.exe的可执行文件,提到了将main.c文件生成a.exe实际上执行了以下四步:
- 预处理
- 编译
- 汇编
- 链接
每一步都有单独的指令,而且生成不同的文件,最后一步才会生成a.exe。下面采用同样的方式打开命令行,按照下列顺序分别输入以下指令,看看每一步你的文件夹下生成了什么新文件。
gcc -E main.c -o main.i
gcc -S main.i -o main.s
gcc -c main.s -o main.o
gcc main.o
gcc main.o -o b.exe
运行了第四个指令,有没有发现文件并没有多,但是a.exe的修改日期变了。这是因为生成的文件名还是a.exe,但是把之前的覆盖了,所以看不到新文件产生。所以这里的第5条指令重新生成并且在生成的同时将生成的文件名变成b.exe。
预处理
第一步预处理,生成了main.i文件,实际上这个-o 后面跟的就是要生成的文件名,我们只是把文件名改成main.i。你可以改成任何的名字,但是后缀尽量不要改。
打开main.i文件,拉到最下方,刚好是之前我们在main.c敲的代码,但是第一行#include<stdio.h>没有了,其实这一步就是把stdio.h的文件拷贝到main.i文件了。
编译
第二步编译,将.i文件编译生成.s文件。.s文件是汇编文件。还记得我们之前过的汇编语言吗,汇编文件就是使用汇编语言编写的文件。这一步就是生成汇编代码文件,如果用记事本打开,显示的内容你可能是看不懂的。这里面就是汇编执行,看看是不是有认识的单词。
汇编
第三步汇编,将.s文件生成.o文件。.o文件是二进制文件,是给计算机看的,即使使用记事本打开,也是你看不懂的乱码。
链接
有人可能会问,上一步汇编后生成的文件已经是二级制文件了,为什么还要第四步链接呢?
链接,这名字听起来就要一个以上的文件才能链接,为什么第四步只有一个文件呢?实际上这一步编译器会在你的电脑里找到他要链接的文件,比如:运行要用的库文件,以及你代码里用到的printf和getchar的真身。虽然把stdio.h复制过来了,但是实际上只复制了它们的名字,他们的真身还在其他文件,这一步就是链接他们的真身,生成可以运行的exe文件。
到后面学习分文件编程的时候,就会发现链接这一步的其他作用。
运行这个b.exe,会发现和a.exe没有什么区别。同样可以使用双击运行和命令行运行。
注释
刚编写完的代码,你肯定是知道的。但是过了一段时间你还记得吗?别人写的代码给你看,你认识吗?我想,简单的代码你可能能看懂,但是上来给你一堆代码,你可能就慌了把。
别慌,我们的前辈们已经想好了一个好办法,那就是注释。既然编写了代码可能会忘,那我就加点自己的注释,用自己的语言来标记。注释,是给人看的,计算机不会翻译它,而且他在编译的预处理那一步就会删除注释。
单行注释
顾名思义,单行注释,只能注释单行,它的语法如下,为了说明,我将为我们编写的main.c写一个注释。
#include<stdio.h>//导入名为stdio.h的头文件
int main()//程序的入口函数main
{
printf("Hello World\n");//打印Hello World!并换行
getchar(); //从键盘获取一个字符
return 0;//main函数的结束,返回0
}
加了以上的注释,阅读代码是不是认识汉字就理解意思了呢。单行注释就是在注释的内容前使用//,告诉编译器这是注释
多行注释
顾名思义,多行注释,肯定能注释多行,它的语法如下,为了说明,我将为我们编写的main.c写一个注释。
/***
这是我编写的第一个程序
文件名:main.c
作者:Point_G
日期:2023.11.29
***/
#include<stdio.h>
int main()
{
printf("Hello World\n");
getchar();
return 0;
}
多行注释的语法就是/*** ***/在这几个星号直接的内容就是注释,可以跨越多行。这种注释一般用于文件头和函数头,说明文件和函数的作用。
预处理注释
这里只做说明,这种语法一般用于注释代码,当你辛苦编写的代码不让用的时候,又不舍得改,可以使用这种语法。想用的时候把#if 0改成#if 1就可以。
#if 0
这是我编写的第一个程序
文件名:main.c
作者:Point_G
日期:2023.11.29
#endif
#include<stdio.h>
int main()
{
printf("Hello World\n");
getchar();
return 0;
}
尝试分布编译运行上面添加注释的三个程序,看看和没有添加注释前,生成的文件有没有不同。
总结
其实以上四步做的不只上面描述的内容,还做了一些其他的事情,在这里给大家总结一下:
- 预处理:头文件的展开、注释的删除、宏定义的替换;关于宏的内容我们后面会讲解,注释的删除,大家可以编写一个带注释的c文件,预处理指令生成的main.i文件看看是否还有注释。
- 编译:词法分析 语法分析 ,程序编写的错误这一步是会检测的,但是只能检测到语法错误,无法检查到逻辑错误。比如:你希望计算机算出3+5的结果,你编写了35+,这就是语法错误,你如果写成2+3,语法没错误,计算机不会报错,但这不是你要求得结果。
- 汇编:将汇编文件生成目标文件 .o 文件
- 链接:链接库文件,生成最终的可执行文件