C 和 C++编译器是集成的.他们都要用四个步骤中的一个或多个处理输入文件: 预处理(preprocessing),编
译(compilation),汇编(assembly)和连接(linking).源文件后缀名标识源文件的 语言,但是对编译器来说,后
缀名控制着缺省设定:
gcc
认为预处理后的文件(.i)是 C 文件,并且设定 C 形式的连接.
g++
认为预处理后的文件(.i)是 C++文件,并且设定 C++形式的连接.
源文件后缀名指出语言种类以及后期的操作:
.c C 源程序;预处理,编译,汇编
.C C++源程序;预处理,编译,汇编
.cc C++源程序;预处理,编译,汇编
.cxx C++源程序;预处理,编译,汇编
.m Objective-C 源程序;预处理,编译,汇编
.i 预处理后的 C 文件;编译,汇编
.ii 预处理后的 C++文件;编译,汇编
.s 汇编语言源程序;汇编
.S 汇编语言源程序;预处理,汇编
.h 预处理器文件;通常不出现在命令行上
其他后缀名的文件被传递给连接器(linker).通常包括:
.o 目标文件(Object file)
.a 归档库文件(Archive file)
除非使用了-c, -S,或-E 选项(或者编译错误阻止了完整的过程),否则连接总是 最后的步骤.在连接阶段中,
所有对应于源程序的.o 文件, -l 库文件,无法识别的文件名(包括指定的 .o 目标文件和.a 库文件)按命令行
中的顺序传递给连接器.
-ansi
支持符合 ANSI 标准的 C 程序
-fno-builtin
不接受不是两个下划线开头的内建函数(built-in function).目前受影响的函数有
_exit, abort, abs, alloca, cos, exit, fabs, labs, memcmp, memcpy, sin, sqrt, strcmp, strcpy,和 strlen.
`-ansi’选项能够阻止 alloca 和_exit 成为内建函数.
-fno-strict-prototype
对于没有参数的函数声明,例如`int foo ();’,按 C 风格处理---即不说明参数个数或类型. (仅针对 C++).正常
情况下,这样的函数 foo 在 C++中意味着参数为空.
-funsigned-char
把 char 定义为无符号类型,如同 unsigned char.
-fsigned-char
把 char 定义为有符号类型,如同 signed char.
这个选项等同于`-fno-unsigned-char’
预处理器选项(Preprocessor Option)
下列选项针对 C 预处理器,预处理器用在正式编译以前,对 C 源文件进行某种处理.
如果指定了`-E’选项, GCC 只进行预处理工作.下面的某些选项必须和`-E’选项一起才 有意义,因为他们的
输出结果不能用于编译.
-nostdinc
不要在标准系统目录中寻找头文件.只搜索`-I’选项指定的目录(以及当前目录,如果合适).
结合使用`-nostdinc’和`-I-’选项,你可以把包含文件搜索限制在显式指定的目录
-E
仅运行 C 预处理器.预处理所有指定的 C 源文件,结果送往标准输出或指定的输出文件.
-C
告诉预处理器不要丢弃注释.配合`-E’选项使用.
-P
告诉预处理器不要产生`#line’命令.配合`-E’选项使用.
-M [ -MG ]
告诉预处理器输出一个适合 make 的规则,用于描述各目标文件的依赖关系.对于每个源文件,预处理器输
出 一个 make 规则,该规则的目标项(target)是源文件对应的目标文件名,依赖项(dependency)是源文件
中 `#include 引用的所有文件.生成的规则可以是单行,但如果太长,就用`\’-换行符续成多行.规则 显示在标
准输出,不产生预处理过的 C 程序.
`-M’隐含了`-E’选项.
-Dmacro
定义宏 macro,宏的内容定义为 1.
-Dmacro=defn
定义宏 macro 的内容为 defn.命令行上所有的`-D’选项在 `-U’选项之前处理.
-Umacro
取消宏 macro. `-U’选项在所有的`-D’选项之后处理,但是优先于任何 `-include’或`-imacros’选项
-dM
告诉预处理器输出有效的宏定义列表(预处理结束时仍然有效的宏定义).该选项需结合`-E’选项使用
汇编器选项(ASSEMBLER OPTION)
-Wa,option
把选项 option 传递给汇编器.如果 option 含有逗号,就在逗号处分割成多个选项
连接器选项(LINKER OPTION)
下面的选项用于编译器连接目标文件,输出可执行文件的时候.如果编译器不进行 连接,他们就毫无意义.
object-file-name
如果某些文件没有特别明确的后缀 a special recognized suffix, GCC 就认为他们是目标文件或库文
件. (根据文件内容,连接器能够区分目标文件和库文件).如果 GCC 执行连接操作,这些目标文件将成为连
接器的输入文件.
-llibrary
连接名为 library 的库文件.
连接器在标准搜索目录中寻找这个库文件,库文件的真正名字是`liblibrary.a’.连接器会 当做文件名得到准
确说明一样引用这个文件.搜索目录除了一些系统标准目录外,还包括用户以`-L’选项指定的路径.
一般说来用这个方法找到的文件是库文件---即由目标文件组成的归档文件(archive file).连接器处理归档
文件的 方法是:扫描归档文件,寻找某些成员,这些成员的符号目前已被引用,不过还没有被定义.但是,如果
连接器找到普通的 目标文件,而不是库文件,就把这个目标文件按平常方式连接进来.指定`-l’选项和指定文
件名的唯一区别是, `-l 选项用`lib’和`.a’把 library 包裹起来,而且搜索一些目录.
-nostartfiles
不连接系统标准启动文件,而标准库文件仍然正常使用.
-nostdlib
不连接系统标准启动文件和标准库文件.只把指定的文件传递给连接器.
-static
在支持动态连接(dynamic linking)的系统上,阻止连接共享库.该选项在其他系统上无效.
-shared
生成一个共享目标文件,他可以和其他目标文件连接产生可执行文件.只有部分系统支持该选项.
-symbolic
建立共享目标文件的时候,把引用绑定到全局符号上.对所有无法解析的引用作出警告(除非用连接编辑选
项 `-Xlinker -z -Xlinker defs’取代).只有部分系统支持该选项.
-Xlinker option
把选项 option 传递给连接器.可以用他传递系统特定的连接选项, GNU CC 无法识别这些选项.
如果需要传递携带参数的选项,你必须使用两次`-Xlinker’,一次传递选项,另一次传递他的参数. 例如,如果
传递`-assert definitions’,你必须写成`-Xlinker -assert -Xlinker definitions’,而不能写成`-Xlinker "-
assert definitions"’,因为这样会把整个 字符串当做一个参数传递,显然这不是连接器期待的.
-Wl,option
把选项 option 传递给连接器.如果 option 中含有逗号,就在逗号处分割成多个选项.
下列选项指定搜索路径,用于查找头文件,库文件,或编译器的某些成员:
-Idir
在头文件的搜索路径列表中添加 dir 目录
-I-
任何在`-I-’前面用`-I’选项指定的搜索路径只适用于`#include "file"’这种情况;他们不能用来搜索
`#include
如果用`-I’选项指定的搜索路径位于`-I-’选项后面,就可以在这些路径中搜索所有的 `#include’指令. (一般说
来-I 选项就是这么用的.)
还有, `-I-’选项能够阻止当前目录(存放当前输入文件的地方)成为搜索`#include "file"’的第一选择.没有办
法克服`-I-’选项的这个效应.你可以指定 `-I.’搜索那个目录,它在调用编译器时是当前目录.这和预处理器的
默认行为不完全一样,但是结果通常 令人满意.
`-I-’不影响使用系统标准目录,因此, `-I-’和`-nostdinc’是不同的选项.
-Ldir
在`-l’选项的搜索路径列表中添加 dir 目录
-w
禁止所有警告信息.
-Wnonnull (禁止是 -Wno-nonnull)
关于为标记为需要非null的参数传递空指针的警告
-Wnonnull-compare
将使用nonnull函数属性标记的参数与函数内的null进行比较时发出警告。
'-Wnonnull-compare'包含在'-Wall'中。 它可以被禁用'-Wno-nonnull-compare'选项。
-Wnull-dereference
如果编译器检测到由于取消引用空指针而触发错误或未定义行为的路径,则发出警告。 此选项仅在以下时有效
'-fdelete-null-pointer-checks'处于活动状态,由优化启用在大多数目标中。 警告的精确度取决于优化使用的选项。
-Wimplicit-int
警告没有指定类型的声明.
-Wimplicit-function-declaration
警告在声明之前就使用的函数.
-Wreturn-type
如果函数定义了返回类型,而默认类型是int型,编译器就发出警告.
同时警告那些不带返回值的return语句,如果他们所属的函数并非void类型.
-Wunused
如果某个局部变量除了声明就没再使用,或者声明了静态函数但是没有定义,或者某条
语句的运算结果显然没有使用,编译器就发出警告.
-Wswitch
如果某条 switch 语句的参数属于枚举类型,但是没有对应的 case 语句使用枚举元素,编译器 就发出警
告. ( default 语句的出现能够防止这个警告.)超出枚举范围的 case 语句同样会 导致这个警告.
-Wswitch-default
每当switch语句没有默认情况时发出警告
-Wunused-function
声明静态函数但未定义静态函数或非内联函数时发出警告静态功能未使用。 '-Wall'启用此警告
-Wunused-parameter
除了声明之外,每当函数参数未使用时发出警告。
-Wunused-result
函数返回值没使用的时候发出警告。
-Wunused-value
只要语句计算明确未使用的结果,就会发出警告
-Wunused
上面所有的‘-Wunused’选项都包含在内
-Wundef
如果在#if指令中计算未定义的标识符,则发出警告。这种标识符被零替换。
-Wunused-macros
警告主文件中定义的未使用的宏
-Winline
如果无法内联声明为内联的函数,则发出警告
-Wcomment
如果注释起始序列`/*’出现在注释中,编译器就发出警告
-Wformat
检查对 printf 和 scanf 等函数的调用,确认各个参数类型和格式串中的一致.
-Wchar-subscripts
警告类型是 char 的数组下标.这是常见错误,程序员经常忘记在某些机器上 char 有符号.
-Wuninitialized
在初始化之前就使用自动变量.
这些警告只可能做优化编译时出现,因为他们需要数据流信息,只有做优化的时候才估算数据流信息.如果
不指定 `-O’选项,就不会出现这些警告.
-Wcast-qual
一旦某个指针强制类型转换以便移除类型修饰符时,编译器就发出警告.例如,如果把 const char * 强制转
换为普通的 char *时,警告就会出现.
-Wcast-align
一旦某个指针类型强制转换时,导致目标所需的地址对齐(alignment)增加,编译器就发出警告.例如,某些机
器上 只能在 2 或 4 字节边界上访问整数,如果在这种机型上把 char *强制转换成 int *类型, 编译器就发出
警告.
-Wstrict-prototypes
如果函数的声明或定义没有指出参数类型,编译器就发出警告. (如果函数的前向引用说明指出了参数类型,
则允许后面 使用旧式风格的函数定义,而不会产生警告.)
-Wmissing-prototypes
如果没有预先声明函数原形就定义了全局函数,编译器就发出警告.即使函数定义自身提供了函数原形也
会产生这个警告. 他的目的是检查没有在头文件中声明的全局函数.
-Wmissing-declarations
如果没有预先声明就定义了全局函数,编译器就发出警告.即使函数定义自身提供了函数原形也会产生这
个警告.这个选项 的目的是检查没有在头文件中声明的全局函数.
-Wredundant-decls
如果在同一个可见域某定义多次声明,编译器就发出警告,即使这些重复声明有效并且毫无差别.
-Wnested-externs
如果某 extern 声明出现在函数内部,编译器就发出警告.
-Wlong-long
如果使用了 long long 类型就发出警告.该警告是缺省项.使用`-Wno-long-long' 选项能够防止这个警告. `-
Wlong-long'和`-Wno-long-long'仅在 `-pedantic'之下才起作用.
-Winline
如果某函数不能内嵌(inline),无论是声明为 inline 或者是指定了-finline-functions 选项,编译器都将发出警
告.
-Werror
视警告为错误;出现任何警告即放弃编译.
-Wstack-protector
此选项仅在'-fstack-protector'处于活动状态时才有效。 它警告说
没有防止堆栈粉碎的功能
GNU CC 拥有许多特别选项,既可以调试用户的程序,也可以对 GCC 排错:
-g
以操作系统的本地格式(stabs, COFF, XCOFF,或 DWARF).产生调试信息. GDB 能够使用这些调试信息.
在大多数使用 stabs 格式的系统上, `-g'选项启动只有 GDB 才使用的额外调试信息;这些信息使 GDB 调试
效果更好,但是有可能导致其他调试器崩溃,或拒绝读入程序.如果你确定要控制是否生成额外的信息, 使用
`-gstabs+', `-gstabs', `-gxcoff+', `-gxcoff', `-gdwarf+',或`-gdwarf' (见下文).
和大多数 C 编译器不同, GNU CC 允许结合使用`-g'和`-O'选项.优化的代码偶尔制造 一些惊异的结果:某
些声明过的变量根本不存在;控制流程直接跑到没有预料到的地方;某些语句因为计算结果是常量或已经
确定而 没有执行;某些语句在其他地方执行,因为他们被移到循环外面了.
然而它证明了调试优化的输出是可能的.对可能含有错误的程序使用优化器是合理的
-ggdb
以本地格式(如果支持)输出调试信息,尽可能包括 GDB 扩展
-print-file-name=library
显示库文件 library 的全路径名,连接时会使用这个库---其他什么事情都不作.根据这个选项, GNU CC 既不
编译,也不连接,仅仅显示文件名.
-print-libgcc-file-name
和`-print-file-name=libgcc.a'一样.
gcc -print-file-name=libc.a a.c
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libc.a
没有生成可执行文件,仅仅打印出路径,其实可以直接
gcc -print-file-name=libc.a 显示路径
这些选项控制多种优化措施:
-O
-O1
优化.对于大函数,优化编译占用稍微多的时间和相当大的内存.
不使用`-O'选项时,编译器的目标是减少编译的开销,使编译结果能够调试.语句是独立的:如果在 两条语句
之间用断点中止程序,你可以对任何变量重新赋值,或者在函数体内把程序计数器指到其他语句,以及从源
程序中 精确地获取你期待的结果.
不使用`-O'选项时,只有声明了 register 的变量才分配使用寄存器.编译结果比不用 `-O'选项的 PCC 要略
逊一筹.
使用了`-O'选项,编译器会试图减少目标码的大小和执行时间
-O2
多优化一些.除了涉及空间和速度交换的优化选项,执行几乎所有的优化工作.例如不进行循环展开(loop
unrolling)和函数内嵌(inlining).和-O 选项比较,这个选项既增加了编译时间,也提高了生成代码的运行效果
-O3
优化的更多.除了打开-O2 所做的一切,它还打开了-finline-functions 选项.
-O0
不优化.
如果指定了多个-O 选项,不管带不带数字,最后一个选项才是生效的选项.
-ffloat-store
不要在寄存器中存放浮点变量.这样可以防止某些机器上不希望的过高精度,如 68000 的浮点寄存器(来自
68881)保存的精度超过了 double 应该具有的精度.
对于大多数程序,过高精度只有好处.但是有些程序严格依赖于 IEEE 浮点数的定义.对这样的程序可以使
用 `-ffloat-store'选项.
-finline-small-functions (反向 -fno-inline-small-functions)
当功能小于预期时,将功能集成到呼叫者中函数调用代码(因此程序的整体大小变小)。
编译器启发式地决定哪些函数足够简单,值得在此集成办法。 此内联适用于所有函数,
甚至是那些未声明为内联函数的函数。启用级别'-O2',' - O3',' - os'
-fstack-protector
检查是否越界
-fstack-protector-all
像'-fstack-protector'一样,但所有功能都受到保护
-EB生成大端代码。
-EL生成小端代码。 这是'mips * el - * - *'配置的默认值。
-msoft-float
不要使用浮点协处理器指令。 实施浮点数是使用库调用进行计算。
-mhard-float
使用浮点协处理器指令。
-G num
把小于等于 num 字节的全局或静态数据放到小的数据段或 bss 段,而不是普通的数据段或 bss 段. 这样汇
编器可以输出基于全局指针(gp 或$28),的单字内存访问指令而非普通的双字指令.默认情况下, 用 MIPS
汇编器时 num 是 8,而 GNU 汇编器则为 0.另外, -Gnum 选项也被传递 给汇编器和连接器.所有的模块必
须在相同的-Gnum 值下编译.
(我们知道,GCC在编译过程,会将变量分别放在data,bss,common等段。
而编译mips程序时,会将小变量放入sdata,sbss,scommon等段。
这个大小由编译选项-G来决定。-G0则表示不使用小数据段。默认是-G8,
表示小于或等于8 byte的数据将放入小变量区。)
下面的选项和平台无关,用于控制目标码生成的接口约定.
大部分选项以`-f'开始.这些选项拥有确定和否定两种格式; `-ffoo'的否定格式是 `-fno-foo'.后面的描述将只
列举其中的一个格式---非默认的格式.你可以通过添加或去掉 `no-'推测出另一个格式.
-fpic
如果支持这种目标机,编译器就生成位置无关目标码.适用于共享库(shared library).
-fPIC
如果支持这种目标机,编译器就输出位置无关目标码.适用于动态连接(dynamic linking),即使分支需要大范
围 转移.
-fshort-double
使 double 类型的大小和 float 一样
-fshared-data
要求编译结果的数据和非 const 变量是共享数据,而不是私有数据.这种差别仅在某些操作系统上面有意义,
那里的共享数据在同一个程序的若干进程间共享,而私有数据在每个进程内都有副件.
-fno-common
即使未初始化的全局变量也分配在目标文件的 bss 段,而不是把它们当做普通块(common block)建立.这
样的 结果是,如果在两个不同的编译结果中声明了同一个变量(没使用 extern ),连接它们时会产生错误. 这
个选项可能有用的唯一情况是,你希望确认程序能在其他系统上运行,而其他系统总是这么做.
-fvolatile
使编译器认为所有通过指针访问的内存是易变内存(volatile).
-fvolatile-global
使编译器认为所有的外部和全局变量是易变内存.