1. gcc简介 gcc/g++是GNU工程的C和C++编译器。都要用四个步骤中的一个或多个处理输入文件。· 预处理(preprocessing)· 编译(compilation)· 汇编(assembly)· 连接(linking) 源文件后缀名标识源文件的语言,但是对编译器来说,后缀名控制着缺省设定。gcc命令的一般格式为:gcc [选项] 要编译的文件 [选项] [目标文件] gcc的详细内容,可参考gcc manual。
2. gcc的输出选项 gcc输出选项,-o后指定输出文件名,gcc解释如下。
| `-o FILE" Place output in file FILE. This applies regardless to whatever sort of output is being produced, whether it be an executable file, an object file, an assembler file or preprocessed C code. If `-o" is not specified, the default is to put an executable file in `a.out", the object file for `SOURCE.SUFFIX" in `SOURCE.o", its assembler file in `SOURCE.s", a precompiled header file in `SOURCE.SUFFIX.gch", and all preprocessed C source on standard output. |
| 指定输出文件为FILE,该选项不考虑GCC产生什么输出,无论是可执行文件、目标文件、汇编文件还是预处理后的C代码。 如果没有使用`-o"选项,默认的输出结果是:可执行文件为a.out,source.suffix的目标文件是source.o,汇编文件是source.s,而预处理后的C代码送往标准输出。 |
3. "hello wolrd"的处理过程 本文以"hello world"程序,探讨GCC编译程序的过程。 hello.c文件内容如下。
| #include <stdio.h> int main(int argc, char **argv){ printf("Hello World! via %x
", printf); return 0;} |
3.1 预处理(preprocessing) 在该阶段,编译器将C源代码中的包含的头文件如stdio.h编译进来,可以使用gcc的选项”-E”进行查看预处理结果。 Gcc manual中对-E选项的解释如下。
| `-E" Stop after the preprocessing stage; do not run the compiler proper. The output is in the form of preprocessed source code, which is sent to the standard output. Input files which don"t require preprocessing are ignored. |
| 预处理后停止,不进行编译。预处理后的代码送往标准输出。GCC忽略任何不需要预处理的输入文件。 |
格式:gcc -E hello.c -o hello.i作用:对hello.c进行预处理输出为hello.i文件 Hello.c被预处理后的hello.i文件。
| # 1 "hello.c"# 1 "<built-in>"# 1 "<command line>"# 1 "hello.c"# 1 "/usr/include/stdio.h" 1 3 4# 28 "/usr/include/stdio.h" 3 4# 1 "/usr/include/features.h" 1 3 4# 335 "/usr/include/features.h" 3 4# 1 "/usr/include/sys/cdefs.h" 1 3 4# 360 "/usr/include/sys/cdefs.h" 3 4# 1 "/usr/include/bits/wordsize.h" 1 3 4# 361 "/usr/include/sys/cdefs.h" 2 3 4# 336 "/usr/include/features.h" 2 3 4# 359 "/usr/include/features.h" 3 4# 1 "/usr/include/gnu/stubs.h" 1 3 4 # 1 "/usr/include/bits/wordsize.h" 1 3 4# 5 "/usr/include/gnu/stubs.h" 2 3 4 # 1 "/usr/include/gnu/stubs-32.h" 1 3 4# 8 "/usr/include/gnu/stubs.h" 2 3 4# 360 "/usr/include/features.h" 2 3 4# 29 "/usr/include/stdio.h" 2 3 4 # 1 "/usr/lib/gcc/i386-RedHat-linux/4.1.2/include/stddef.h" 1 3 4# 214 "/usr/lib/gcc/i386-redhat-linux/4.1.2/include/stddef.h" 3 4typedef unsigned int size_t;# 35 "/usr/include/stdio.h" 2 3 4 # 1 "/usr/include/bits/types.h" 1 3 4# 28 "/usr/include/bits/types.h" 3 4# 1 "/usr/include/bits/wordsize.h" 1 3 4# 29 "/usr/include/bits/types.h" 2 3 4 typedef unsigned char __u_char;typedef unsigned short int __u_short;typedef unsigned int __u_int;typedef unsigned long int __u_long; typedef signed char __int8_t;typedef unsigned char __uint8_t;typedef signed short int __int16_t;typedef unsigned short int __uint16_t;typedef signed int __int32_t;typedef unsigned int __uint32_t; __extension__ typedef signed long long int __int64_t;__extension__ typedef unsigned long long int __uint64_t; __extension__ typedef long long int __quad_t;__extension__ typedef unsigned long long int __u_quad_t;# 131 "/usr/include/bits/types.h" 3 4# 1 "/usr/include/bits/typesizes.h" 1 3 4# 132 "/usr/include/bits/types.h" 2 3 4 ... |
3.2 编译(compilation) 在这个阶段中,Gcc首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,Gcc把代码翻译成汇编语言。可以使用”-S”选项来进行查看,该选项只进行编译而不进行汇编,生成汇编代码。 Gcc manual中对-S选项的解释如下。
| `-S" Stop after the stage of compilation proper; do not assemble. The output is in the form of an assembler code file for each non-assembler input file specified. By default, the assembler file name for a source file is made by replacing the suffix `.c", `.i", etc., with `.s". Input files that don"t require compilation are ignored. |
| 编译后即停止,不进行汇编。对于每个输入的非汇编语言文件,输出文件是汇编语言文件。 缺省情况下,GCC通过用`.o"替换源文件名后缀`.c",`.i"等以产生目标文件名。可以使用-o选项指定选择其他名字。GCC忽略任何不需要编译的输入文件。 |
格式:gcc –S hello.i –o hello.s 作用:将预处理输出文件hello.i汇编成hello.s文件 Hello.i被汇编后的hello.s文件。
| .file "hello.c" .section .rodata.LC0: .string "Hello World! via %x
" .text.globl main .type main, @functionmain: leal 4(%esp), %ecx andl $-16, %esp pushl -4(%ecx) pushl %ebp movl %esp, %ebp pushl %ecx subl $20, %esp movl $printf, 4(%esp) movl $.LC0, (%esp) call printf movl $0, %eax addl $20, %esp popl %ecx popl %ebp leal -4(%ecx), %esp ret .size main, .-main .ident "GCC: (GNU) 4.1.2 20070925 (Red Hat 4.1.2-33)" .section .note.GNU-stack,"",@progbits |