文章目录
- 一、编译工具gcc/g++
- 二、程序编译的过程
- 🎄预处理
- 🎄编译
- 🎄汇编
- 🎄链接
- 三、动态链接和静态链接
- 🌻动态链接
- 🌻静态链接
- 🌻 程序动、静态链接的区分
一、编译工具gcc/g++
gcc/g++ 分别是 C/C++ 的编译器,基本使用方法:
$ gcc [选项] 编译文件 [选项] 目标文件
$ g++ [选项] 编译文件 [选项] 目标文件
二、程序编译的过程
在学习gcc/g++之前,我们先了解一下程序的翻译过程
🎄预处理
预处理可以完成的工作:头文件展开、去注释、宏替换、条件编译
在以前学习中,我们是使用gcc/g++它是直接完成程序编译的过程,生成可执行文件,若我们想一步一步的看清楚过程,我们可以执行下面这样的一句指令,让代码预处理完之后就停下来:
gcc -E test.c -o test.i
-E
让翻译在预处理完成后就停下来-o
可以指定生成的目标文件名称,预处理完的文件一般后缀为.i
🎄编译
编译时,gcc会检查代码的规范性、是否有语法错误,以确定代码所做的工作,检查无误后gcc会把C语言处理为汇编语言。
gcc -S test.i -o test.s
-S
让程序的翻译在完成编译后就停下来- 一般编译结束后生成的代码文件的后缀为
.s
编译阶段生成的汇编代码,以供接下来的汇编阶段使用。
🎄汇编
汇编阶段会将编译阶段所形成的汇编代码文件变为一个二进制文件
gcc -c test.s -o test.o
-c
让程序的翻译,做完汇编工作,变成可重定向目标二进制文件,就停下来- 一般汇编结束后生成的代码文件的后缀为
.o
注意: 虽然生成的是二进制目标文件,但仍然不可以直接运行,准确来说该文件是可重定向的目标文件。相当于Windows下的.obj
文件。
🎄链接
预处理、编译、汇编三个阶段统称为编译过程,完成了上述的编译过程,就到了程序翻译的最后一个阶段:链接。
链接完成后,就会生成可执行程序
gcc test.o -o test
默认生成的可执行程序名称为a.out
,-o
选项可以自己定义名称
三、动态链接和静态链接
函数库的概念:
语言本省会提供库,例如,C语言提供的C标准库。我们通常使用printf
、scanf
等等库函数,都是实现在库文件中的。我们自己只是写了这些函数的调用,没有对应的实现,只有当链接的时候,对应的实现,才和我们的代码关联起来。
🌻动态链接
通过链接器和库建立链接。直白理解就是当我们需要调用库中某些函数时,直接去库中查找
动态链接的优缺点
- 优点:形成的可执行程序较小,下载便捷;节省内存,磁盘的存储空间
- 缺点:依赖第三方库,每次执行程序都需要进行链接,所以运行速度相对慢一点
🌻静态链接
链接的时候,不是与库产生关联,而是将程序内部需要使用的方法,拷贝一份,完成静态链接。
静态链接的优缺点
-
优点:
- 在可执行程序中已经具备了所有执行程序所需要的任何东西,在执行的时候运行速度比较快
- 不依赖第三方库,不受库升级或被删除的影响
-
缺点:形成的可执行程序体积大
🌻 程序动、静态链接的区分
1. 查看程序是动、静态的方法
file 可执行程序
dynamically linked:中文意思就是动态链接
2. 查看程序依赖的库
ldd 可执行程序
3. 在Linux下库的命名
- 动态库:libXXX.so
- 静态库:libYYY.a
区分:
去掉前缀lib
,去掉后缀.so
,剩下的即使库的名称。
例如:libc.so.6依赖的就是C标准库
4. 使用静态链接
Linux中可执行程序默认使用动态链接,如果需使用静态链接,需要添加-static
选项
gcc mytest.c -o mytest_static -static #采用静态链接方式
注意:
一般而言,系统会自动携带动态库,静态库如果不存在,需要自己安装
sudo yum install -y glibc-static #安装C静态库
sudo yum install -y libstdc++-static #安装C++静态库
5. 静态链接,从库中拷贝的代码,是从哪个库中拷贝?
静态链接需要系统中存在静态库,从该静态库中拷贝代码。
6. Windows下的动静态库的区分
- 动态:
.dll
- 静态:
.lib