编译过程
- 引子
- 编译阶段
- 预处理
- 汇编
- 编译
- 链接
- 链接详解
- release && debug
引子
一个程序的编译分为4个部分:
- 预处理
- 头文件的展开
- 条件编译
- 宏的展开
- 去掉注释
- 编译
生成汇编 - 汇编
生成计算机认识的机器指令, 即二进制文件 - 链接
将程序和库
链接
🗨️这里有一个疑问: 在汇编阶段, 已经生成了机器指令. 按理说, 应该就可以结束了, 那为什么还要连链接?
- 首先, 先明确, 链接阶段是和
库
做链接.
那么, 库又是什么?
库是各种方法的实现方式, 而我们熟知的 头文件是各种方法的声明.
那么, 方法又是什么?
比较常见的, 如: printf, cout, cin … …, 这些我们常常会用到的方法, 就会将它写入库中
在后面的学习中, 我们还知道链接是分动态链接
和静态链接
的, 它们又有什么区别呢? 咋们后面再说
编译阶段
预处理
gcc -E 源文件 -o 目标文件
-E
是gcc关于预处理的选项, 后面的文件是源文件
-o
后面是生成的目标文件
. 一般预处理的文件后缀是.i
3. 宏
在预处理过程中是平替过去的, 所以不会有语法检查
4. 条件编译其实在日常生活中是非常常见的. 比如: 拿视频的普通用户 和 VIP用户来说, 其实就是利用条件编译 将VIP用户的部分功能 剪枝
掉, 才有的普通用户的功能, 那么这样就只用维护一段代码就可以了.
汇编
gcc -S 预处理文件/源文件 -o 目标文件
-S
是gcc关于汇编的选项, 后面跟的是源文件
-o
后面跟的是目标文件
. 一般汇编的目标文件的后缀是.s
编译
gcc -c 源文件/汇编文件 -o 目标文件
-
-c
是gcc关于编译的选项, 后面跟的是源文件
-
-o
后面跟的是目标文件
. 一般汇编的目标文件的后缀是.o
-
生成的是机器可识别指令, 即
二进制文件
-
假如 目标文件是
test.o
, 我们管 test.o 也叫作可重定位目标二进制文件
, 简称目标文件
. 目标文件不能单独运行, 要通过和库
进行链接才能运行👇👇👇
🗨️有人便会说 权限不够
导致的
- 文件的执行权限是
x
, 那我们就给 test.o 文件加入x
权限👇👇👇
权限是能不能做, 但是你即使可以做, 但是有些人就是不让你做这件事情!
社会就是如此的残酷
链接
gcc 源文件 -o 目标文件
- 链接没有选项
- -o 后面跟目标文件
总结:
1 . 链接阶段没有选项, 前面的选项依次是ESc
2. 链接阶段没有强调后缀名, 前面的后缀名依次是iso
🗨️这些选项 ESc
有什么功能啊?
- 首先, 我们发现
链接阶段
, gcc 源文件 -o 目标文件 是直接编译完成的
其次, 我们发现, 在我们加入了这些选项之后, gcc好像是遇到了什么阻碍, 翻译到那里就停止了.
由此, 我们便可得出结论: - -E :告诉gcc翻译到预处理就停止翻译
- -S : 告诉gcc翻译到汇编就停止翻译
- -c : 告诉gcc翻译到编译就停止翻译
链接详解
通过前面的学习, 我们知道了编译的各个阶段以及各个阶段编译器做的事情.
可重定位目标二进制文件不能单独运行, 必须和 库
链接了才能运行.
库是各种方法的实现形式, 头文件的各种方法的声明.
🗨️那么, Linux下库在哪里, 长什么样子?
- 在这里, 科普一下:
- Windows下是有静态库(
.lib
) 和 动态库(.dll
)的,
Linux下也是有静态库(.a
) 和 动态库(.so
) 的. - Linux下库的
命名规则
— — libname
.xxx(后缀), 所以我们查C语言的库
就是libc.so 或 libc.
- Linux下
库的路径
— —/usr/lib/... ...
我们发现, Linux下C语言库默认是有动态库的, 但是没有静态库
, 我们也可以这样理解 C语言的标准库就是动态库
, 默认的链接方式是动态链接
由此出现几个问题:
- C语言静态库如何安装?
sudo yum -y install glibc-static — — 安装C语言的静态库
sudo yum -y install libstdc+±static — — 安装C++的静态库
- 如何使用静态链接?
gcc 源文件 -o 目标文件 -static
-
为什么C语言库默认是动态库呢?
使用静态库进行的链接是静态链接
, 使用动态库进行的链接是动态链接
两种链接方式的区别:- 动态链接 — — 通过C语言编译器将源文件所需要的动态库的链接告知 可执行程序
- 静态链接 — — 将源文件所需要的静态库拷贝到可执行程序中.
通过比较两种链接方式, 我们可以得知: 通过动态链接方式, 最后生成的可执行程序的大小 要
小于
通过静态链接方式生成的可执行文件的大小⇒ 这样可以有效地节省空间(磁盘空间, 内存空间, 网络空间等等)👇👇👇
-
一个可执行文件是单纯动态链接还是静态链接还是动静态混合链接?
在没有静态库的情况下, 那就是动态链接喽
在有静态链接的情况下:- 加-static, 那就是强制使用静态链接
- 没加-static, 那就是动静态混合链接
file 可执行文件 — — 查看此可执行文件的链接方式
ldd 可执行文件 — — 查看此可执行文件所依赖的动态库
release && debug
在VS上, 默认生成的可执行文件是 debug版本
,
而在Linux上, 默认生成的可执行文件是 release版本
.
如果要变成debug版本
, 那要在编译的时候加 -g
🗨️何为debug版本?
- debug版本就是在可执行文件中
添加
了调试信息
添加, 添加 ⇒ 那就意味着, 最后生成的可执行文件的空间要变大👇👇👇
debug版本
是我们之后学习的 gdb调试
的基础.
弟子曰:有所忿懥,如何?
阳明曰:只是个物来顺应,不要着一分意思,便心体廓然大公,得其本体之正了。
译文:
弟子问:情绪不好,愤怒怨恨怎么办?
先生说:顺其自然,不要沾上主观意气,就能保持本心的平静。
愤怒的情绪很正常,每个人都会有。
但是如果任由自己发泄情绪,往往会造成不可挽回的伤害。
王阳明给出的方法是:戒掉主观,人尽量不要把自己代入。
用旁观者的角度,来看待这个问题,人的情绪就会减弱很多。
苏轼有云:
不识庐山真面目,只缘身在此山中。
学会旁观,让自己跳出来,人生才能不被情绪控制,不被愠怒左右。