编译器gcc/g++、动静态库
- [1.gcc / g++的工作流程](#1.gcc / g++的工作流程)
1.gcc / g++的工作流程
1.编译过程
- 预处理:宏替换,取注释,头文件展开,条件编译。
- 编译:将 C 语言,变成汇编语言。
- 汇编:将汇编语言,变成机器可以识别的代码。
2.链接过程
链接:将目标文件与一些库链接在一起,生成可执行文件。
选项:-ESC 对应文件后缀 .iso
3.三大问题
1.如何理解条件编译?
条件编译的用途?
- 软件进行专业度收费情况,使用条件编译进行代码的动态裁剪(免费版在收费版的基础上阉割掉了一些功能)
- 内核源代码也是采用条件编译进行代码裁剪。
- 开发工具、应用软件等,在不同的平台下(Linux / Windows)都可以运行,只需要一份经过条件编译的代码即可。
2.为什么C/C++编译,要先变成汇编语言?
由于历史发展的原因:
- 计算机初期是打孔编程(二进制编程)
- 由于打孔编程效率低,接着汇编语言诞生(二进制编写的),这里就需要编译器将汇编语言转化成计算机可以识别的二进制。
- 又由于汇编语言写程序还是较为困难,C语言诞生(汇编编写的),这里就需要编译器将C语言转化成汇编语言好呢?还是转化成二进制好呢?答案当然是汇编语言。
- 再后来就是:C++/Java/golang/python,都是一个语言编写另一个语言,形成了百家争鸣的场面,若要都转化成二进制,工作量是非常巨大的,干脆站在巨人的肩膀上转化为汇编语言。
3.编译器的发展?
- 要发明一门语言,首先需要编译器向下编译成更加低层的语言。
- 现在的问题:编译汇编语言成二进制的编译器,是由什么编写的呢?总不能是汇编写的吧!答案:二进制版的编译器,编译汇编语言成二进制。接着用汇编语言写一个汇编编译器,从此以后二进制版的编译器就不用了,诞生了第一个由汇编语言写的编译器来编译汇编语言成二进制。该过程叫做:编译器的自举过程。
- 同理C语言也是以上过程。
4.函数库
1.什么是库?
- 库是一套方法 / 数据集,为我们开发提供最基本的保证(基本接口,功能),加速我们的二次开发。
- 我们的C程序中,并没有定义 "printf" 的函数实现,且在预编译中包含的 "stdio.h" 中也只有该函数的声明,而没有定义函数的实现,那么是在哪里实 "printf" 函数的呢?
- 答案是:系统把这些函数实现都被做到名为 libc.so.6 的库文件中,在没有特别指定时,gcc 会到系统默认的搜索路径 "/usr/lib" 下进行查找,也就是链接到 libc.so.6 函数库中去,这样就能实现函数 "printf" 了,而这也就是链接的作用。
2.动态库和静态库
函数库一般分为静态库和动态库两种。
- 静态库是一种将多个目标文件(通常是编译后的代码文件,如 .o 文件或 .obj 文件)打包在一起的文件格式。在编译链接时,链接器会将静态库中的代码直接拷贝到最终的可执行文件中。这意味着每个使用静态库的程序都会有一份库的副本,因此会导致可执行文件较大。
- 动态库是一种包含代码和数据的文件,这些代码和数据可以在运行时被多个程序共享。动态库在程序运行时加载到内存中。这意味着多个程序可以共享同一个动态库,从而节省磁盘空间和内存。
动态库和静态库的对比:
- 动态库形成的可执行程序体积比静态库小。
- 静态库形成了可执行程序后,就不再需要静态库,可执行程序对静态库的依赖度小。动态库不能缺失,否则会导致程序无法执行。
- 程序运行需要加载到内存。静态链接,会在内存中出现大量的重复代码。
- 动态链接,比较节省内存和磁盘资源。
动态库:Linux(.os文件)Windows(.dll文件)
静态库:Linux(.a文件)Windows(.lib文件)
3.动态链接和静态链接
- 动态链接则发生在程序运行时,而不是编译时。当程序启动时,动态链接器(或装载器)会负责将程序所需的动态库(共享库)加载到内存中,并解析程序中的符号引用。与静态链接不同,动态链接允许多个程序共享同一个库文件的代码和数据,从而节省磁盘和内存空间。此外,动态链接还使得程序能够在运行时更新其依赖的库,而无需重新编译整个程序。
- 静态链接发生在程序的编译和链接过程中,当编译器将源代码编译成目标文件后,链接器会将这些目标文件以及所需的静态库合并成一个单一的可执行文件。在这个过程中,链接器会解析所有的符号引用,并将所需的库代码直接嵌入到可执行文件中。因此,静态链接的可执行文件在运行时不再需要额外的库文件,因为它们已经包含了所有必要的代码和数据。
4.gcc / g++:默认动态链接,使用动态库
gcc
如何进行静态链接?前提:静态库必须存在,系统默认安装的是动态库,静态库需要自行安装
bash
#CentOS下安装静态库指令
sudo yum install -y glibc-static
g++
bash
#下载g++编译器
sudo yum install -y gcc-c++
bash
#安装C++静态库
sudo yum install -y libstdc++-static
图解
Linux中的指令大部分都是由C编写的,都需要依赖C动态库,若C动态库被删除了,这些指令都无法使用了。
5.库和链接的本质
一个场景:不想暴露源文件。