# 写在前面
本文主要介绍`Linux`下`gcc`编译的知识
# gcc
## gcc介绍
`gcc`最开始的时候是 `GNU C Compiler`, 如你所知,就是一个`c`编译器。但是后来因为这个项目里边集成了更多其他不同语言的编译器,所以表示一堆编译器的合集。 `g++`则是`GCC`的`c++`编译器。
现在你在编译代码时调用的`gcc`,已经不是当初那个`c`语言编译器了。更确切的说他是一个驱动程序,根据代码的后缀名来判断调用`c`编译器还是`c++`编译器 `g++`。比如你的代码后缀是`.c`,他会调用`c`编译器还有`linker`去链接`c`的`library`。如果你的代码后缀是`.cpp`, 他会调用`g++`编译器,当然`library call`也是`c++`版本的。当然我说了这么多你可能感到有些混乱,没关系,你就把gcc当成c语言编译器,g++当成c++语言编译器用就是了。
## 安装
- `sudo apt-get install g++`
- `g++ --version` 判断是否安装成功
## gcc编译的四个步骤
gcc编译程序可分为四个步骤:`预处理 --> 编译 --> 汇编 --> 链接`

### gcc常用参数
- `-I`:指定头文件所在的目录
- `-c`:只做预处理、编译、汇编,得到二进制文件
- `-g`:编译时添加调试语句,主要用于`gdb`调试
- `Wall`:显示所有警告信息
- '-D':向程序中动态注册宏定义
- '-O':
### 数据段合并

图例解释:
- `.text`:存放程序运行代码(机器码)
- `.rodata`:只读数据段
- `.data`:存放了经过初始化的全局变量和静态变量
- `.bss`:保存了那些用到但未被初始化的数据
### 地址回填
在代码内调用自己的函数有一个统一的地址,在程序未执行时 `main` 函数地址为`0`,假设代码如下
```cpp
#include<stdio.h>
void fun1(){
}
void fun2(){
}
int main(){
fun1();
fun2();
}
```
在程序未执行时,代码中的函数都是没有地址的,`fun1`与`fun2`函数的地址为`main`函数的地址加上一个数值,也就是,代码中剩余的函数地址是基于`main`的,地址为`main地址 + x`,当程序开始执行时,内存会分给`main`函数确切的地址,此时会把原来代替的地址回填到`main地址 + x`中,该过程为地址回填。
Linux系统编程(一)