目录
[一 编译器](#一 编译器)
[1 翻译的过程(重点放在编译选项上)](#1 翻译的过程(重点放在编译选项上))
[a 预处理(进行宏替换)](#a 预处理(进行宏替换))
[b 编译](#b 编译)
[c 汇编](#c 汇编)
[d 链接](#d 链接)
[2 一般程序的构建过程(.o文件)](#2 一般程序的构建过程(.o文件))
[3 条件编译](#3 条件编译)
[4 编译器/语言的历史](#4 编译器/语言的历史)
[5 编译器和对应语言的关系:自举](#5 编译器和对应语言的关系:自举)
[6 链接](#6 链接)
(2)关于链接和指令查看:ldd关于链接和指令查看:ldd)
一 编译器
gcc 是 C 语言编译器,g++ 是 C++ 编译器(本质上 G++ 也能编译 C 代码,相当于将C代码转变为C++代码去进行编译,但习惯上 C 用gcc,C++ 用 g++)
编译的本质:将源文件翻译成可执行二进制文件
1 翻译的过程(重点放在编译选项上)
a 预处理(进行宏替换)
我们先在code.c中写入代码,文件包含头文件,宏,注释

如果一次性将整个代码编译完,是看不到翻译过程的

预处理指令:gcc -E code.c -o code.i:将翻译过程放到code.i的临时文件中
预处理的工作:头文件展开、去注释、宏替换、条件编译
vim code.i
code.c文件中的去注释、头文件展开、宏替换的效果都是由预处理产生的
头文件展开:就是把头文件相关内容拷贝到源文件!!头源合并的过程! (编译器只需要再预处理时需要头文件)
当我们把code.c翻译为code.i文件时,code.i还是头文件,它是一个非常干净的c语言,里面没有一个注释和宏替换

b 编译
编译 :C语言变为汇编语言
编译指令 :gcc -S code.i -o code.s

c 汇编
汇编:汇编语言变为目标文件(.o/.obj(可重定位二进制目标文件))

结束汇编时,我们不能正常运行code.o文件,还需要链接
d 链接
需要再链接的时候,把我们的.o和C标准库链接形成可执行!
链接指令: gcc code.o -o code.exe
可以这样记忆:ESc -> iso
2 一般程序的构建过程(.o文件)
gcc -c code.c:直接形成同名.o文件

提高效率:gcc -o code.exe code.o

当有很多的源文件时,先把源文件编译成.o文件,然后再把.o链接
所谓的头文件展开,就是把你include包含的头文件拷贝到你所在的源文件中,就是文件合并的过程
3 条件编译
我们在c语言的部分学过条件编译,如果忘记了我们来复习一下:

那我我们在Linux下写一段条件编译的代码:

我们发现在main函数部分,V1并没有被定义,所以编译器不会执行Version1(),会直接被编译器裁剪掉
这种方式可以由编译器在预处理阶段根据特定的条件进行代码裁剪,把这种特性叫做条件编译
预处理器可以对写的c语言代码实现增删查改的,所以预处理器就有一种能力------>可以对我的源文件做二次编辑
所以条件编译本质是文本处理

用条件编译实现不同商业化版本软件的管理
4 编译器/语言的历史


5 编译器和对应语言的关系:自举
编译器的自举是指:用目标语言(如 C++)编写的编译器,最终能编译自身源代码。这是现代编程语言(如 C++、Golang、Rust)的标准实现方式,核心解决 "如何从无到有构建目标语言编译器" 的问题。

6 链接
(1)初步理解

(2)关于链接和指令查看:ldd
ldd:查看文件依赖哪个库

关于链接:
动态库---->通常和程序进行动态链接静态库---->通常和程序进行静态链接
(3)动态库和静态库
静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大(大不少,前面展示过了),但在运行时也就不再需要库文件了。其后缀名一般为".a"。
动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由
运行时链接文件加载库,这样可以节省系统的开销。动态库一般后缀名为"so",如前面所述的libc.so.6就是动态库。gcc在编译时默认使用动态库。完成了链接之后,gcc就可以生成可执行文件
(4)感性的理解库和链接
动态库的小故事:
假如说你是张三,你考上了当地的一中,但是这个一中管理非常的严格,不能带手机,于是你问学长学校附近哪里有上网的地方,学长给你说学校的东门出去向左100米,向右100米,有一家电竞馆,于是你决定在学校里完成任务之后,出去上网,但是随着去电竞馆的人越来越多,电竞馆就被举报了,110就来关闭了电竞馆。

静态库的小故事:
当电竞馆因为举报关闭了之后,张三就没地方上网了,张三就给他爸说,让他爸爸从网吧老板那里买了一台电脑放到了张三的宿舍里,大家发现可以从老板那里买电脑之后,越来越多的人买了电脑回去

(5)gcc是默认动态链接

(6)两个细节
细节1:如果我删掉c动态库呢?
一般而言,系统中大部分指令(c/c++编写的二进制指令)就无法运行了
细节2:gcc默认使用动态库和动态链接
Linux系统中,默认之安装了动态库,怎么办?
我们手动安装一下静态库就可以了
# Centos
yum install glibc-static libstdc++-static -y
静态库是指编译链接时,把库文件的代码全部加⼊到可执行文件中,因此生成的文件比较大,但在运
行时也就不再需要库文件了。其后缀名⼀般为".a"
• 动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由
运行时链接文件加载库,这样可以节省系统的开销。动态库⼀般后缀名为".so",如前⾯所述的
libc.so.6就是动态库。gcc在编译时默认使用动态库 。完成了链接之后,gcc就可以生成可执行文
件,如下所示。 gcc hello.o --o hello
