今天我们来了解一下Linux中的编译器,gcc,g++,编译器,顺便来了解一下程序的翻译过程。
程序的翻译过程
程序的翻译过程一般分为一下几个阶段:预处理,编译,汇编,连接。下面我们用gcc给大家演示一下,不同的·翻译阶段编译器都干了什么:
预处理
预处理,会把包含的头文件展开,会删掉注释等,我们来验证一下:
我们先用vim编写一段简单的代码:
我们此时只想让程序只走到预处理阶段,所以我们在编译时带上选项 -E形成的文件名后缀为**.i**:
g其中-o + 文件名 是 **将处理之后的文件指定到另一个文件中。**现在我们用vim将code.i打开看看:
我们看到经过预处理之后多了很多行的代码,那是因为被我们包含的头文件stdio.h被在code.c中展开了,而我们也发现之前的注释都被消除掉了。
其实预处理主要做以下这几件事:
- 头文件展开
- 去注释
- 条件编译
- 宏替换
我们依次来试一下:
发现不管是条件编译,还是宏都被替换掉了。
编译
预处理完毕之后接下来就是编译了,编译是将刚才的code.i进行汇编翻译,翻译成汇编指令。,选项是:** -S**,形成的文件名后缀是**.s**:
汇编
在这一步编译器会将汇编指令翻译成可重定位二进制文件,这个可重定位二进制文件,说白了,就是二进制文件,这个文件只有电脑才读的懂了。
选项:-c 形成的文件名后缀为**.o**:
这个时候code.o全都是乱码了,只有电脑才会读得懂了。
链接
此时还有最后一步链接,此时不用带选项:
此时code.o进行连接之后变成了可执行文件,文件名为mybin,我们可以查看一下:
我们将这个可执行文件执行一下:
此时程序的翻译全部完成!但是中间有一个问题这个连接是怎么连接的呢?
此时我们要介绍两种连接方式动态链接和静态链接。
动态链接:通过入口访问库函数地址,以链接的方式关联起来。
静态链接:无时链接,库函数就在本地,直接调用。
动态链接的优点是体积小,节省资源,而静态链接无视链接可以直接运行,我们的gcc默认使用的是动态链接,如果想要用静态链接,我们加上选项:static。
此时我们来查看一下静态链接编译之后的文件大小:
我们发现a.out比mybin大的多,静态编译的缺点之一。
如果发现无法运行,可能是,没有安装相应的静态库,大家可以按照这个安装:
sudo yum install -y glibc-static //C语言静态库
C++静态库:
同时我们也可以查看动态库,动态链接的库的地址都来自这个动态库:
ls /lib64/libc.so.6
我们也可以查看我们安装的静态库:
ls /lib64/libc.a
教大家怎么看库的名字: