一、快速认识gcc和g++
gcc和g++都是编译器,C语言可以用gcc或者是g++来进行编译,但推荐使用gcc来进行编译。但C++语言只能用g++编译器来进行编译。
1.1语言和编译器的自举的过程
为了更好地认识gcc和g++,在这里可以给大家介绍一下语言和编译器的自举的过程。在早期计算机刚产生的时候其实是只有二进制代码的,也只有用二进制代码写的编译器,直到后来有了汇编语言的诞生。但是汇编语言产生之初是没有可以编译汇编语言的编译器的,那怎么办呢?人们只好先用二进制语言写一个汇编编译器,这样才可以编译汇编代码。汇编代码可以在用二进制语言写的汇编编译器上运行以后,也就意味着人们可以使用汇编代码写程序进而写软件了,这时用汇编代码写的汇编编译器(编译器同样是一款软件)也就应运而生了。同样的道理,C语言刚产生的时候,同样没有用C语言写的C语言编译器,只有用汇编语言写的C语言编译器,后来才可以用C语言来写C语言编译器。从此以后,C语言就可以用C语言来编译了,这就叫语言的自举过程。
1.2语言的翻译过程
从上面语言的自举过程我们可以看到,语言的翻译过程是分阶段的。也就是说,假设要将C语言翻译成二进制语言,绝不是一步到位地直接将C语言直接翻译成二进制语言,一定是先将C语言翻译成汇编语言,再将汇编语言翻译成二进制语言。因为将C语言翻译成汇编语言,将汇编语言翻译成二进制语言这两个工作在语言的发展过程中前人所写过的编译器已经可以实现这两个功能,所以说语言的翻译过程一定是分阶段的,所以也就有了预处理,编译,汇编,链接这几个步骤。
二、程序的翻译过程
1、预处理
1.1头文件展开
所谓的头文件展开,其实在预处理阶段的时候,将头文件的内容拷贝至源文件当中。
1.2去注释
1.3宏替换
1.4条件编译
ifdef,elif,endif
-D选项可以动态地给代码增加条件,实现条件编译
预处理完C语言程序还是C语言程序。
gcc -E C文件名 -o 所形成的文件的文件名,-E的意思就是从现在开始程序的翻译过程,当预处理阶段做完的时候就停下来。
2、编译
-S的意思就是从现在开始程序的翻译过程,当编译阶段做完的时候就停下来。编译完形成的文件就是汇编代码了。
3、汇编
-c的意思就是从现在开始程序的翻译过程,当汇编阶段做完的时候就停下来。汇编过程形成的.o文件叫可重定位二进制文件,这个二进制文件是不能执行的,需要经过链接过程才能形成可执行程序。
4、链接
链接就是可以形成可执行程序。我们需要知道的是,平台要支持开发,就必须提前在系统中安装好语言的头文件和库文件, 链接的实质就是将我们自己写的程序所形成的.o文件同系统提供的静态库或动态库中的.o文件链接起来形成可执行程序。
三、动静态库的理解
动静态库其实就是一系列.o文件。
动态库:.so,用于动态链接
静态库:.a,用于静态链接
静态链接:将自己需要的代码直接拷贝到自己的可执行程序中。所以说,允许你进行拷贝的库就叫做静态库,拷贝完以后我的可执行程序就不需要再依赖于库了。静态库的优点就是不需要再依赖于库,程序在同类型平台中都可以直接运行使用。缺点也是比较明显的,就是可执行程序的体积会比较大,比较占据资源(磁盘资源,网络资源,内存资源)。
动态链接:允许你进行链接的库就叫做动态库。可执行程序依据编译器所给出的动态库的地址去动态库中找到相应的方法进行链接,这个过程就叫做库调用。找到以后进行函数返回,链接完成后可执行程序就可以运行了。动态库的优点就是比较节省资源,不同的程序中不会出现过多重复的代码。缺点就是一旦库丢失,所有依赖于该库的程序就都不能运行了。
gcc -o 所形成的文件的文件名 C文件名这条指令默认是使用静态链接的,如果想使用静态链接形成可执行程序,要使用gcc -o 所形成的文件的文件名 C文件名 -static这条指令。动态链接是gcc的默认行为,