左手编程,右手年华。大家好,我是一点,重视我,带你走入编程的世界。

公众号:一点sir,重视领取编程材料

一般咱们用IDE写完一个程序后,点击编译按钮的时分,内部究竟发生了什么?为什么会生成一个可执行文件?这个进程究竟有哪些进程呢?是很简略仍是很杂乱呢?这篇文章,咱们把这些事情讲清楚。

首先要清晰一点,编译只是一个统称,编译的整个进程有预处理、编译、汇编和链接的进程

咱们给出一个特别简略的程序

//test.c
#include <stdio.h>
#define max 5
int main()
{
    printf("max = %dn", max);
    return 0;
}

1、预处理

预处理阶段的指令一般都是以#来开头的,替换#include包括的头文件,替换#define界说的宏,删去注释,去掉#ifdef不符合条件的那一部分,所有#开头的代码都会在预处理阶段完结处理。

预处理指令:gcc -E test.c -o test.i

这儿-E的作用是让程序在预处理完结之后就中止,为了方便咱们后边的观察。咱们在当时目录下ls,就能够看见多了一个test.i的文件,打开它能够看到许多变量、函数等等的声明,这些都是stdio.h这个头文件展开的结果,拉到最终,能够看到咱们界说的宏max被替换成5了。

C++程序编译之谜——简略仍是杂乱?编译究竟有哪些进程?
)

2、编译

大学假如学的是计算机专业的童鞋一定会学过一门《编译原理》的课,这门课简直会把许多大学生折腾得死去活来。而这个编译的进程也正式编译原理里边介绍的内容,包括词法剖析、语法剖析、语义剖析、程序优化等等一系列的进程,这些都是编译器的核心内容,假如你想开发编译器,这个进程你要十分十分的精通!这个进程便是把程序编译成更接近机器语言的汇编语言。平时咱们用IDE编译的时分,经常看见的过错和正告,一般都是在进程宣布的。

编译指令:gcc -S test.i -o test.s

这儿-S的作用是让程序在编译完结之后就中止,为了方便咱们后边的观察。咱们在当时目录下ls,就能够看见多了一个test.s的文件,打开它看到的一大堆汇编指令。这些指令,我根本看不明白,说实话,没有触摸过汇编语言的人,简直都是看不明白的。可是假如你是想在编译器这个底层范畴翻江倒海的话,汇编语言是必需要懂的。

C++程序编译之谜——简略仍是杂乱?编译究竟有哪些进程?

3、汇编

汇编语言有些专业人员看得懂,可是计算机是根本就看不明白的。计算机看得懂的只是只要010101这种机器语言,所以咱们还要将汇编语言转换成机器语言,至于这个进程怎么转的,不在本文的评论范围,也评论不了,由于我也不知道。这些都是那些十分厉害的大神的研讨范畴,真不是我夸大这个难度,能开宣布商用编译器的人,至少在计算机范畴绝对都是逆天的天选之子。

汇编指令:gcc -C test.i -o test.o

咱们在当时目录下ls,就能够看见多了一个test.o的文件,打开它看到的一大堆乱码,实际上这些都是二进制指令,而这些指令才是计算机能看得懂的。

4、链接

二进制文件尽管计算机能够看懂了,可是假如你的源文件中用到了其他自己写的头文件的函数,或者是第三方静态库动态库,这时分还需要进行把它们链接起来生成可执行文件,才干够正确的被执行。

链接指令:gcc test.o -o test

可是假如引用的头文件是C/C 语言等级自带的话,换种说法便是,只要一个源文件,貌似不需要进行链接这一步,直接运行上面编译生成的.o文件也能够。反而进行链接操作的话会报这个过错,原因我暂时也没找到,假如知道的朋友欢迎留言评论。

/opt/rh/devtoolset-9/root/usr/libexec/gcc/x86_64-redhat-linux/9/ld: error in test.o(.eh_frame); no .eh_frame_hdr table will be created

以上便是编译的几个进程,只要比较清晰地把握好每个进程,才干真实地把编译的整个流程搞清楚。当然,你也能够用一步到位的方法进行编译:

gcc test.c -o test