# C 程序编译工具
## 6.1 gcc编译系统
目前LInux平台上最常用的C语言编译系统是gcc(GNU Compiler Collection)
### 6.1.1 文件名后缀
常用的文件后缀及其表示文件类型
| 文件名后缀 | 文件类型 |
| --------------- | ------------------------ |
| .c | C 源文件 |
| .i | 预处理后的C源文件 |
| .ii | 预处理后的C++源文件 |
| .C .cc .cp .cpp | C++源文件 |
| .c++ .cxx | |
| .h | C或C++头文件 |
| .s | 汇编程序文件 |
| .S | 必须预处理的汇编程序文件 |
| .o | 目标文件 |
| .a | 静态连接文件 |
| .so | 动态连接库 |
### 6.1.2 C语言编译过程
- **1、预处理,生成 .i 的文件[预处理器cpp]**
- **2、将预处理后的文件转换成汇编语言, 生成文件 .s [编译器egcs]**
- **3、有汇编变为目标代码(机器代码)生成 .o 的文件[汇编器as]**
- **4、连接目标代码, 生成可执行程序 [链接器ld]**
### 6.1.3 gcc命令行选项
#### 预处理选项
| 选项 | 解释 |
| :----------- | :----------------------------------------------------------- |
| -ansi | 只支持 ANSI 标准的 C 语法。这一选项将禁止 GNU C 的某些特色, 例如 asm 或 typeof 关键词。 |
| -c | 只编译并生成目标文件。 |
| -DMACRO | 以字符串"1"定义 MACRO 宏。 |
| -DMACRO=DEFN | 以字符串"DEFN"定义 MACRO 宏。 |
| -E | 只运行 C 预编译器。 |
| -g | 生成调试信息。GNU 调试器可利用该信息。 |
| -IDIRECTORY | 指定额外的头文件搜索路径DIRECTORY。 |
| -LDIRECTORY | 指定额外的函数库搜索路径DIRECTORY。 |
| -lLIBRARY | 连接时搜索指定的函数库LIBRARY。 |
| -m486 | 针对 486 进行代码优化。 |
| -o FILE | 生成指定的输出文件。用在生成可执行文件时。 |
| -O0 | 不进行优化处理。 |
| -O 或 -O1 | 优化生成代码。 |
| -O2 | 进一步优化。 |
| -O3 | 比 -O2 更进一步优化,包括 inline 函数。 |
| -shared | 生成共享目标文件。通常用在建立共享库时。 |
| -static | 禁止使用共享连接。 |
| -UMACRO | 取消对 MACRO 宏的定义。 |
| -w | 不生成任何警告信息。 |
| -Wall | 生成所有警告信息。 |
## 6.2 gdb程序调试工具
**错误类型三种:**
1. **编译错误**
2. **运行程序**
3. **逻辑错误**
**工作流程**
1. **启动程序**
2. **试运行程序在置顶处停止**
3. **当程序停止时,检查**
4. **动态改变程序的执行环境**
### 6.2.1 启动和查看内部命令
> https://www.jianshu.com/p/adcf474f5561
**基本格式**
```linux
gdb [-help] [-nx] [-q] [-batch] [-cd=dir] [-f] [-b bps] [-tty=dev] [-s symfile] [-e prog] [-se prog] [-c core] [-x cmds] [-d dir] [prog [core|procID]]
gdb [options] --args prog [arguments]
gdbtui [options]
```
| 命令 | 功能 |
| ----------- | -------------------------------------------------- |
| r | run, 直接调到断点处,没有设置断点的话直接运行程序 |
| b fun | 设置一个断点breakpoint在函数”fun”的最开始 |
| b N | 在当前运行源文件的第N行设置断点 |
| b file.c:N | 在当前源文件file.c的第N行设置断点 |
| d N | 删掉delete第N行的断点 |
| info break | 显示所有断点信息 |
| c | 继续(continue)运行程序,一直到下一个断点或程序结束 |
| f | 运行直到当前函数(function)结束 |
| s | 按step调试1行,会进入函数体 |
| s N | 按step调试接下来的N行 |
| n | 调试1行,与按s命令不同的是此处不进入函数体 |
| p var | 输出(print)变量”var”的值 |
| set var=val | 设置变量”var”的值 |
| bt | 打印调用堆栈(stack trace) |
| q | 退出gdb |
**例**
**代码**
```c
//main.c
#include <stdio.h>
int main()
{
int balance=100;
int target=1000;
float rate = 0.1;
int year = 0;
do
{
float interest = balance * rate;
balance = balance + interest;
year++;
} while ( balance >= target );
printf("%d No. of years to achieve target balance.\n", year);
return 0;
}
```
**效果**
```
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
```
**步骤1**:编译并构建程序,加上调试选项-g
> gcc -g main.c -o test.out
**步骤2**:用GDB来运行程序
> gdb test.out
**步骤3**:在main函数入口处设置一个断点
> b main
**步骤4**:运行程序
> run
**步骤5**:使用step调试到13行
> s
**步骤6**:查看balance, rate, interest的值
> p balance
> p rate
> p interest
**步骤7**:使用step调试到15行
**步骤8**:查看balance, rate, interest的值(发现没有循环,表明while条件出错,应该是balance < target)
