工学1号馆

home

« | 返回首页 | »

使用GCC编译器(2)-- 编译C程序

By Wu Yudong on December 08, 2016

这篇文章中,介绍了 gcc 编译、优化c程序的过程,本文将详细介绍gcc执行的四个步骤(预处理、编译、汇编、链接),来控制编译过程。

当 gcc 执行时,默认的行为是基于源代码产生可执行文件,举个例子

$ gcc -Wall circle.c

-Wall 命令在程序出现问题的时候给出警告,如果没问题则生成一个默认名为a.out的可执行文件

$ ./a.out

如果想指定名字为circle,则使用下面的命令:

$ gcc -Wall  -o circle circle.c

预处理

在源代码传给编译器之前,预处理器会执行预处理指令,展开源代码中的宏,默认情况下gcc不会保留预处理阶段的中间输出文件,但可以选择利用 -E 选项来保留中间输出文件,以便观察预处理结果。

注意:-E 选项会造成gcc在预处理结束后立即停止

可以使用 -o 选项将中间输出文件导入到某个文件:

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

如果想阻止编译器删除注释,可以使用-C 选项

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

编译

gcc 一般会把汇编语言输出到临时文件,并且在汇编执行完后立即删除,但可以使用-S 选项,让编译程序让汇编输出后立即停止,默认汇编语言的输出在一个.s 为后缀名的文件中

$ gcc -S circle.c

汇编

gcc 调用宿主系统的汇编器,将汇编语言翻译成可执行的二进制文件,二进制文件是一个对象文件,包含机器码和行源文件指定的功能,也包含一个符号表,描述源文件中有外部链接的所有对象

使用-c 选项,gcc不会链接临时文件,直接产生文件后缀名为.o的对象文件

$ gcc -c circle.c

将产生名为 circle.o 的对象文件

使用gcc 的-Wa 选项把命令行选项传递给汇编,例如,希望汇编器使用下面的选项

-as=circle.sym

在一个单独的列表中输出模块的符号表,并把指定的列表输出到名为 circle.sym 的文件中

-L 在符号表内包含局部符号

接着可以让 gcc 在引用汇编器时加上这些选项, 选项用逗号分隔成一个列表,放在 -Wa 选项中:

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

注意:-Wa 后面必须紧跟一个逗号,后面接着选项列表,选项之间完全不能有空格

在汇编器的-a 选项后加上多个开关选项,如果使用时没有指定开关选项,默认输出包含汇编语言的程序代码,后面跟着符号表。

gcc的 -g 选项让编译器在输出中包含调试信息,如果同时包含-a 选项和 -g 选项会发生什么呢?

$ gcc -g -o hello -Wa,-as=hello.list,-L hello.c

上述命令执行结果文件是 hello.list

链接

链接器把多个二进制对象文件链接成单一的可执行文件。在链接过程中,必须完成程序中多个模块之间的外部参考,把“参数符号”用对象实际位置代换。链接器还必须将程序中所用到的C标准链接库内的函数加入其中。

标准链接库的大部分内容一般放在libc.a 中,或者放在动态链接的共享版本libc.so中,这些链接库一般位于/lib/或者/usr/lib/,或者位于GCC 默认情况下会搜索的其他链接库目录。

-save-temps 选项可以一次获得全部的中间输出文件,例如

wu@ubuntu:~/cfun$ gcc -save-temps hello.c

执行完后,出现不同后缀名的各种文件,具体如下

wu@ubuntu:~/cfun$ ls
a.out  hello.c  hello.c~  hello.i  hello.o  hello.s

.i 表示预处理输出文件,.s 表示汇编语言输出,.o 表示对象文件

如果文章对您有帮助,欢迎点击下方按钮打赏作者

Comments

No comments yet.
To verify that you are human, please fill in "七"(required)