GCC的编译流程分为以下4个步骤
-
预处理(pre-processing)
-
编译(compiling)
-
汇编(assembling)
-
链接(linking)
编译器通过程序的扩展名来分辩编写源程序所用的语言。由于不同的程序所需要执行编译的步骤是不同的,因此GCC根据不同的后缀名对它们进行相应处理。
GCC所支持不同后缀名的处理方式
后 缀 名 | 所对应的语言 | 编 译 流 程 |
---|---|---|
.c | C 原始程序 | 预处理、编译、汇编 |
.C/.cc/.cxx | C++原始程序 | 预处理、编译、汇编 |
.m | Objective C 原始程序 | 预处理、编译、汇编 |
.i | 已经过预处理的C 原始程序 | 编译、汇编 |
.ii | 已经过预处理的C++原始程序 | 编译、汇编 |
.s/.S | 汇编语言原始程序 | 汇编 |
.h | 预处理文件(头文件) | (不常出现在指令行) |
.o | 目标文件 | 链接 |
.a/.so | 编译后的库文件 | 链接 |
GCC编译流程语法
GCC基本语法
gcc [option | filename]
这里的 option 是 GCC 使用时的一些选项,通过指定不同的选项 GCC 可以实现强大的功能。这里的 filename 则是 GCC 要编译的文件,GCC 会根据用户所指定的编译选项以及所识别的文件后缀名来对编译文件进行相应的处理。
- 预处理阶段
GCC 的选项“-E”可以使编译器在预处理结束时就停止编译,选项“-o”是指定 GCC 输出的结果,其命令格式如下:
gcc –E –o [目标文件] [编译文件]
例如: gcc –E –o hello.i hello.c
2.编译阶段
编译器在预处理结束之后使用。GCC首先要检查代码的规范性、是否有语法错误等,以确定代码实际要做的工作,在检查无误后,就开始把代码翻译成汇编语言。GCC的选项“-S”能使编译器在进行完编译之后就停止。
gcc –S –o [目标文件] [编译文件]
例如: gcc –S –o hello.s hello.i
3.汇编阶段 汇编阶段是把编译阶段生成的“.s”文件生成目标文件,读者在此使用选项“-c”就可看到汇编代码已转化为“.o”的二进制目标代码了。
gcc –c [目标文件] [编译文件]
例如: gcc –c hello.s –o hello.o
4.链接阶段 成功编译之后,就进入了链接阶段。在这里涉及一个重要的概念:函数库。 完成链接之后,GCC 就可以生成可执行文件,其命令如下:
gcc hello.o –o hello
GCC警告提示
GCC 的警告提示选项有很多种类型,主要可分为“-Wall”类和非“-Wall”类。
1.Wall类警告提示
这一类警告提示选项占了GCC警告选项的90%以上,它不仅包含打开所有警告等功能,还可以单独对常见错误分别指定警告。
选项 | 作用 |
---|---|
-Wall | 打开所有类型语法警告,建议读者养成使用该选项的习惯 |
-Wchar-subscripts | 如果数组使用char 类型变量作为下标值的话,则发出警告。因为在某些平台上可能默认为 signed char,一旦溢出,就可能导致某些意外的结果 |
-Wcomment | 当“/”出现在“/ …… */”注释中,或者“\”出现在“// ……”注释结尾处时,使用-Wcomment 会给出警告,它很可能会影响程序的运行结果 |
-Wformat | 检查 printf 和 scanf 等格式化输出输入函数的格式字符串与参数类型的匹配情况,如果发现不匹配则发出警告。某些时候格式字符串与参数类型的不匹配会导致程序运行错误, 所以这是个很有用的警告选项 |
-Wimplicit | 该警告选项实际上是-Wimplicit-int 和-Wimplicit-function-declaration 两个警告选项的集合。前者在声明函数却未指明函数返回类型时给出警告,后者则是在函数声明前调用该函数时给出警告 |
-Wmissing-braces | 当聚合类型或者数组变量的初始化表达式没有充分用括号“{}”括起时,给出警告 |
-Wparentheses | 这是一个很有用的警告选项,它能帮助用户从那些看起来语法正确但却由于操作符优先级或者代码结构“障眼”而导致错误运行的代码中解脱出来 |
-Wsequence-point | 关于顺序点(sequence point),在 C 标准中有解释,不过很晦涩。我们在平时编码中尽量避免写出与实现相关、受实现影响的代码便是了。而-Wsequence-point 选项恰恰可以帮我们这个忙,它可以帮我们查出这样的代码来,并给出其警告 |
-Wswitch | 这个选项的功能浅显易懂,通过文字描述也可以清晰地说明。当以一个枚举类型(enum) 作为 switch 语句的索引但却没有处理 default 情况,或者没有处理所有枚举类型定义范围内的情况时,该选项会给出警告 |
-Wunused-function | 警告存在一个未使用的static 函数的定义或者存在一个只声明却未定义的static 函数 |
-Wunused-label | 用来警告存在一个使用了却未定义或者存在一个定义了却未使用的label |
-Wunused-variable | 用来警告存在一个定义了却未使用的局部变量或者非常量static 变量 |
-Wunused-value | 用来警告一个显式计算表达式的结果未被使用 |
-Wunused-parameter | 用来警告一个函数的参数在函数的实现中并未被用到 |
-Wuninitialized | 该警告选项用于检查一个局部自动变量在使用之前是否已经初始化或者在一个 longjmp 调用可能修改一个non-volatile automatic variable 时给出警告 |
这些警告提示可以根据自己的不同情况进行相应的选择,这里最为常用的是“-Wall”。
2.非 Wall 类警告提示
非 Wall 类的警告提示中最为常用的有以下两种:“-ansi”和“-pedantic”。
-
“-ansi”。该选项强制 GCC 生成标准语法所要求的告警信息,尽管这还并不能保证所有没有警告的程序都是符合ANSI C 标准的。
-
“-pedantic”。该选项允许发出 ANSI C 标准所列的全部警告信息,同样也保证所有没有警告的程序都是符合 ANSI C 标准的。