【Linux】gcc/g++工具篇
目录
- 一、gcc vs g++
- 1.1 预处理
- 1.2 编译
- 1.3 汇编
- 1.4 链接
- 二、动静态库
- 2.1 什么是动静态库?
个人主页<—请点击
Linux专栏<—请点击
一、gcc vs g++
gcc
是C语言
编译器,只能用来编译C语言
,而g++
是C++/C语言
编译器,两者都可编译。它们两者的选项绝大部分完全一样。
程序翻译共分为四个过程,分别是预处理、编译、汇编、链接
。在之前的文章已经提到过多次了,今天,我们详细了解这四个过程。
1.1 预处理
预处理部分会进行a.头文件展开 b.去注释 c.宏替换 d.条件编译
。
现在准备了一段代码:
#include <stdio.h>#define MAX 100int main()
{#ifdef TEST_IFprintf("条件编译1\n");
#else printf("条件编译2\n");
#endifprintf("hello world,%d\n",MAX);//printf("hello world,%d\n",MAX);//printf("hello world,%d\n",MAX);//printf("hello world,%d\n",MAX);//printf("hello world,%d\n",MAX);printf("hello world,%d\n",MAX);return 0;
}
这段代码中包含了上面提到的四个部分,按照我们的预期,在预处理阶段完成后,头文件会展开,代码中注释的部分会去掉,使用到的宏定义会被替换,条件编译会执行。
选项-E:程序开始编译,在做完对程序的预处理后停下来,-o:用于指定输出文件的名称
。
接下来形成对源文件进行预处理后的文件。
如上图在进行预处理后文件的大小明显增加。下图是预处理进行的工作。
如上图,条件编译的本质是对代码做裁剪,它的用途我们举个例子:一家公司的软件有vip
功能,当你是普通用户时,公司呈现的就是免费版本,将收费的功能裁剪掉,而当你是vip
时,就呈现出全部功能,控制免费版本和收费版本可以通过条件编译来实现。
1.2 编译
选项-S:程序开始翻译,把C语言翻译成汇编语言后停下来
。
为什么要把C语言
翻译成汇编语言
? 翻译语言的本质是转换成CPU
能够识别的指令集。
CPU
不能直接理解高级语言如C语言
。它只能理解和执行特定的指令集架构ISA
对应的二进制机器代码。
语言的发展是从二进制
到汇编
再到C语言
等高级语言。
汇编语言编译器的任务就是将汇编语言编译好的代码转化成二进制指令,这就比二进制编程要好的多了,但还是难以理解,于是在历史的洪流下,C语言
就诞生了,此时就面临一个问题,C语言编译器
是将C语言
直接翻译成二进制,还是翻译成汇编语言呢?
前人在几十年里已经将汇编语言做的很好了,汇编语言到二进制的翻译过程很完备了,于是将C语言翻译成为汇编语言是大势所趋。
这里还有一个值得注意的地方,在汇编语言在发明之前,是没有编译器的,此时是先将汇编语言的规则制定出来,然后使用前一代语言也就是二进制编译出一个粗糙的汇编编译器,然后在使用这个编译器编写汇编代码,汇编重写汇编编译器,这叫做编译器自举
。
1.3 汇编
选项-c:程序开始翻译,将汇编语言翻译成为二进制后停下来
。
上面提到二进制指令CPU
是能够识别的,那我们给code.o
加上可执行权限,尝试执行code.o
,看看能不能运行吧。
如上图,运行失败了,为什么呢? 原因是源文件中使用了库函数,而头文件中只有库函数的声明,没有定义,所以无法运行。
1.4 链接
将二进制文件经过链接形成可执行程序。
开发C语言
需要三个方面,编译器、头文件、库文件
。头文件中有库函数的声明,而库文件中存在库函数的定义,链接过程将源文件中使用到的库函数与库进行了关联。
二、动静态库
Linux
下静态库是以.a
结尾的,动态库是以.so
结尾的。以动态库为例libname.so
,去掉前面的lib
和后面的.so
之后就是库的名字,如上图中的libc-2.17.so
,C标准库的名字是c-2.17
。
2.1 什么是动静态库?
动态库在程序运行时才被加载到内存中。多个程序可以共享同一个动态库文件。你可以把它想象成“公共仓库”或“插件”。链接动态库的过程叫做动态链接,由动态链接器完成。
优点:节省内存空间;缺点:速度慢,编译完成依旧依赖动态库。
静态库在编译链接期被直接整合到最终的可执行程序中。你可以把它想象成“复制粘贴”。当程序编译时,编译器会将静态库中用到的代码完整地拷贝到你的程序中。链接静态库的过程叫做静态链接,由链接器完成。
优点:不需要库跳转,一旦编译成功,不依赖库;缺点:形成的可执行程序体积较大,消耗内存资源。
想要使用静态链接,首先要保证安装了静态库:sudo yum install glibc-static
。
这就是安装好的静态库。
gcc
选项-static
:强制要求gcc
采用静态链接的方式。
如上图,静态链接比动态链接形成的可执行文件整整大了大约100
倍。
动态链接和动态链接都可以正常运行:
最佳实践:编译程序采用动态库和动态链接的方式。
总结:
以上就是本期博客分享的全部内容啦!如果觉得文章还不错的话可以三连支持一下,你的支持就是我前进最大的动力!
技术的探索永无止境! 道阻且长,行则将至!后续我会给大家带来更多优质博客内容,欢迎关注我的CSDN账号,我们一同成长!
(~ ̄▽ ̄)~