C核心技术手册(三十七)

18.3.1 进阶

  下面的小节介绍GCC的选项,使用你可以控制编译过程的每个阶段:预处理、编译、装配和连接。你也可以执行单独的步骤来调用单独的工具,例如C预处理器cpp,汇编程序as,

连接器ldGCC也可被配置来使用指定主机上的外部程序,为了统一,本章描述如何执行这四步来控制程序。

18.3.1.1 预处理

  在将程序向实际的编译器提交前,预处理器执行指示符和扩展源代码中的宏,GCC通常不会保留预处理阶段的结果,但是你可以使用-E选项将预处理阶段输出保存下来以便以后诊断程序时使用。此选项将使用GCC在预处理完成后停止。预处理器直接将结果输出在标准输出设备上。除非你使用-o选项指定一个输出文件名。

# gcc -E -o circle.i circle.c

因为头文件比较大,预处理器输出文件通常包含通常不用的标题。

你可能会出现-c 选项很有用,因为它可以使预处理器移除注释和头文件:

# gcc -E -C -o circle.i circle.c

下列选项通常用来影响GCC在预处理阶段的行为:

-D name[= definition]

  在预处理源代码之前定义符号name,name不能定义在它们自己的源文件或头文件中。将这个选项目与指示符#ifdef name一起使用来控制编译。

-U name

  Name将为未定义的符号,如果它被定义在命令行或GCC的默认设置中,当它出现在命令行中时,-D-U选项用来处理其。

-I directory[: directory[…]]

  当使用#include包含头文件后,在除系统标准的include目录外的指定目录下寻找它们。

通常的查找顺序为:

1.         源文件所在目录(在#include中使用引号””

2.         在命令行中使用-I选项指定的目录

3.         在环境变量C_INCLUDE_PATHCPATH中指定的目录

4.         系统默认的include目录

-I-

  此选项将命令行中-I directory选项分为两组,所有附加在-I-左边的目录不会被查找,例如:

#include <stdio.h>

  做为替代,他们仅查找在#include中使用引号包含的头文件,因此:

  #include “myheader.h”

  第二组由-I-右边的按指示符组成,无论任何#include指示符,这些目录将被查找。

  此外,如果-I-出现在命令行中,则包含源文件的目录将不再被做为第一个被用来查找头文件。

18.3.1.2 编译

  编译器的核心工作就是将C程序翻译成汇编语言,汇编语言是接近真实机器代码的易于人理解的程序设计语言,因此,每个CPU体系架构具有不同的汇编语言。

  通常GCC将汇编语言的输出保存在一个临时文件中,当汇编程序运行时立刻删除它们,但你可以使用-s选项,使编译程序在产生汇编输出后停止,如果不指定一个输出文件名,使用-s选项的GCC将默认使用.s为后缀的文件来存储汇编文件。例如:

 $ gcc –S circle.c

编译器预编译circle.c并将其翻译成汇编语言,将结果存储在circle.s中,如果要在结果文件中和注释一样包含C变量的名子,需要使用附加选项 –fverbose-asm;

$ gcc -S -fverbose-asm circle.c

18.3.1.3 装配

  因为每种机器体系结构均有自己特有的汇编语言,GCC调用它宿言主系统上的汇编程序将汇编语言翻译成可执行的二进制代码,结果为一个object文件,它包含了源文件中定义的各函数对应的机器码,并包含一个描述所有具有外部连接的对象的符号表(symbol table)。

  如果你使用GCC在一个命令行中完成编译和连接, 这时object 文件是临时的,当连接器运行时它将被删除。然而大多数情况下,编译连接是独立的,-c选项目可以指示GCC不要连接程序,但是为每一个输入文件生成一个以源文件名命令的,后缀为.o的文件。

$ gcc -c circle.c

此命令生成一个object文件circle.o

可以使用-Wa选项来将命令选项目传递给汇编程序,例如,假设我们想让汇编器带下面的参数运行:

-as=circle.sym

它将以一个单独的列表将模块符号表打印出来,并保存在一个以源文件名命令的,后缀为.sym的文件中。

-L

包括本地符号表,即具有内部连接的C标识符。

我们可以在GCC的参数中使用-Wa来带上汇编器的参数,如下:

$ gcc -v -o circle -Wa,-as=circle.sym,-L circle.c

命令列表中-Wa后必须有一个逗号,具不能包含空格。-v选项让GCC打印出编译时第一步使用的参数,允许你看到汇编命令行的结果。

可以在汇编器的-a选中增加几个开关来控制列表的输出,详细信息可以查看汇编器的手册, 如果使用没带参数的-a选项目,将会产生默认的列表输出,它包含汇编代码和符号表。

GCC的选项目可以使用编译器在输出文件中包含调试信息,如果附加-g选项,生成的汇编结果将包含C源代码的行信息。

$ gcc -g -o circle -Wa,-a=circle.list,-L circle.c

结果列表文件为circle.list,允许你按行检查编译器如何进行C语句的翻译。

posted @ 2011-04-17 23:29  Socrates  阅读(131)  评论(0编辑  收藏  举报