1.简介
GNU CC(简称gcc)是GNU项目中符合ANSI C标准的编译系统,能够编C、C++、Object C、java、Fortran、Pascal、Modula-3和Ada等多种语言,而且gcc是一个交叉平台编译器,能够在当前CPU平台上为多种不同体系结构的硬件平台开发软件,因此尤其适合在嵌入式领域的开发编译。
后缀名 | 所对应的语言 | 后缀名 | 所对应的语言 |
---|---|---|---|
.c | C原始程序 | .s/.S | 汇编语言原始程序 |
.C/.cc/.cxx | C++原始程序 | .h | 预处理文件(头文件) |
.m | Objective-C原始程序 | .o | 目标文件 |
.i | 已经过预处理的C原始程序 | .a/.so | 编译后的库文件 |
.ii | 已经过预处理的C++原始程序 | ... | ... |
2.gcc编译流程解析
gcc的编译流程分为四个步骤:
(1)预处理(Pre-Processing)
在这个阶段,编译器将对包含的头文件(#include)和宏定义(#define、#ifdef)等编译进文件中。
如:gcc -E hello.c -o hello.i (-E的作用是让gcc在预处理结束后停止编译过程)
(2)编译阶段
在编译阶段,gcc首先要检测代码的规范性、是否错误等,在检测无误后将代码翻译成汇编语言。
如:gcc -S hello.i -o hello.s(-S的作用是让gcc在编译阶段结束后停止编译过程)
(3)汇编阶段
汇编阶段是把编译阶段生成的.s文件转成目标文件。
如:gcc -c hello.s -o hello.o(-c的作用是将.s文件转化为.o文件(二进制代码))
(4)链接阶段
链接阶段有一个重要的概念:库函数(库函数分为静态库和动态库两种)。
1)静态库:指编译链接时,将库文件的代码全部加入可执行文件中,因此生成的文件比较大,但是运行时就不再需要库文件,后缀通常为.a。
2)动态库:在编译链接阶段,并没有将库代码添加到可执行文件中,而是在程序运行时加载库,这样可以节省系统的开销,后缀通常为.so。
如:gcc hello.o -o hello,接着执行./hello则可获得正确的结果。
3.gcc编译选项分析
PS:gcc可用选项主要包括总体选项、告警和出错选项、优化选项和体系结构相关选项。
(1)常用选项
选项 | 含义 |
---|---|
-c | 只编译不链接,生成目标文件.o |
-S | 只编译不汇编,生产汇编代码.s |
-E | 只进行预处理,不做其他处理 |
-g | 在可执行程序中包含标准调试信息 |
-o file | 将file文件指定为输出文件 |
-v | 打印出编译器内部编译各过程的命令行星系和编译器的版本 |
-I dir | 在头文件的收索路径列表中添加dir目录 |
PS:在include语句中,“<>”表示在标准路径中搜索头文件,“ “” ”表示在本目录中搜索。
(2)库选项
选项 | 含义 |
---|---|
-static | 进行静态编译,即链接静态库,禁止使用动态库 |
-shared | 1.可以生成动态库文件 2.进行动态编译,尽可能地链接动态库,只有当没有动态库时才会链接同名的静态库(默认选项,可省略) |
-L dir | 在库文件的搜索路径列表中添加dir路径 |
-lname | 链接称为libname.a(静态库)或者libname.so(动态库)的库文件。若两个库都存在,则根据编译方式(-static还是-shared)而进行链接 |
-fPIC(或-fpic) | 生成使用相对地址的位置无关的目标代码(Position Independent Code)。然后通常使用gcc的-static选项从该PIC目标文件生成动态库文件 |
(3)告警和出错选项
选项 | 含义 |
---|---|
-ansi | 支持符合ANSI标准的C程序 |
-pedantic | 允许发出ANSI C标准所列的全部警告信息 |
-pedantic-error | 允许发出ANSI C标准所列的全部出错信息 |
-w | 关闭所有告警 |
-Wall | 允许发出gcc提供的所有有用的告警信息 |
-werror | 吧所有的告警信息转化为错误信息,并在告警发生时终止程序编译过程 |
(4)优化选项
gcc可以对代码进行优化,它通过编译选项“-On”来控制优化代码的生成,其中n是一个代表优化级别的整数。
虽然优化选项可以加速代码的运行速度,但是经过优化后,原先在源程序中声明和使用的变量很可能不再使用,控制流也可能会突然跳转到意外的地方,循环语句也有可能因为循环展开而变得到处都有,所有这些对调试来讲都将是一场噩梦。
(5)体系结构相关选项
选项 | 含义 |
---|---|
-mcpu=type | 针对不同的CPU使用相应的CPU指令。可选择的type有i386、i486、pentium及i686等 |
-mieee-fp | 使用IEEE标准进行浮点数的比较 |
-mno-ieee-fp | 不使用IEEE标准进行浮点数的比较 |
-msoft-float | 输出包含浮点库调用的目标代码 |
-mshort | 把int类型作为16位处理,相当于short init |
-mrtd | 强行将函数参数个数固定的函数用ret NUM返回,节省调用函数的一条指令 |