这里我们需要知道gcc和g++实际上是对应的c语言和c++编译器,而其他的Java(半解释型),PHP,Python等语言实际上是解释型语言,因此我们经常能听到c语言是偏向底层的语言
我们这里就以c语言为例,进行基础的讲解
我们知道计算机只能处理二进制代码,而在计算机发展的过程中,将二进制代码是用类似打孔纸带的东西承载的,再之后发展就是由汇编语言,将众多常用的二进制代码用助记符来表示,之后再由汇编语言发展而来的各类底层语言,也就是c语言
那我们把上面的过程反过来,就是电脑能够理解我们所写代码含义的过程了,也就称之为编译
在编译的过程中实际上分为四个阶段
那我们能否将编译的过程分段查看呢,其实在Linux中是可以做到的,只需要用一些指令即可
在这个阶段中,主要做一些准备工作,例如头文件展开,删除注释,条件编译,宏替换,这些工作都是在预处理阶段完成的,例如
我们首先使用vim创建一个c语言文件
vim test.c
#include
int main()
{
int i = 0;
int sum = 0;
for(; i <= 10; i++)
{
sum += i;
}
printf("%d\n", sum);
return 0;
}
我们使用gcc进行编译就可以直接产生一个可执行文件,这里我们可以用选项使他只进行预处理阶段的内容
gcc -E test.c -o test.i
这里的-E选项代表只进行预处理阶段的处理,-o表示生成文件的名称,我们一般把后缀名命名为i
可以使用vim可以看到里面的内容
这里我们可以看到内容还是很多的,直接生成了八百多行的内容,因为他把stdio的内容全都转移到这个文件中了
但是我们还是可以看懂其中的内容的,说明他还是处于c语言阶段,并没有到汇编的内容
实际上这一阶段就会将程序翻译成汇编语言,我们同样可以使用选项来查看内容
例如
gcc -S test.i -o test.s
这里的代码对于没有学过汇编语言的人来说已经读不懂了,只能大概看懂里面的一些单词
这一过程就是将汇编转成可重定位的二进制文件,目前就只需要知道他是不可执行的即可
gcc -c test.s -o test.o
链接实际上就是字面意思,但是链接的是什么东西呢,实际上是对于函数库链接
我们在学习c语言的阶段了解过,需要包含stdio.h的头文件才可以进行一些格式化输入输出函数的使用,他其实就是函数库
在Linux中,有一个库文件叫做libc.so.6,在没有指定时,gcc会到默认路径下进行查找,再对其进行链接,这样就可以准确的调用到对应的函数了
对于这样的文件,libc.so.6,lib是前缀,后面的so之类的都是后缀,所以我们可以知道这个库其实是由c语言编写出来的
函数库一般分为两种,动态库和静态库
静态库是指编译链接时,将库文件的代码全部加入到可执行文件中,因此生成的文件也比较大,在运行时也不怎么需要库文件了,后缀名一般为a
动态库就是链接的主体了,这样做可以节省系统的开销,后缀名是so,在编译的过程中,gcc默认使用动态库,这样链接完成之后就会形成可执行文件了
选项 | 说明 |
---|---|
-E | 只预处理 |
-S | 只编译到汇编 |
-c | 编译到目标代码 |
-o | 生成可执行文件 |
-static | 采用静态链接 |
-g | 生成调试信息,GNU调试器可以利用该信息 |
-O0 | / 无优化 |
-O1 | / 缺省值 |
-O2 | / |
-O3 | 编译器优化的四个级别 |
-w | 不生成任何警告 |
-Wall | 生成所有警告信息 |
-shared | 尽可能使用动态库 |
感谢各位的支持,如果你发现文章中有任何不严谨或者需要补充的部分,欢迎在评论区指出