编译过程
1在预处理阶段
输入的是C语言源文件,通常为.c或者.C,它们一般带有h之类的头文件。这个阶段主要处理源文件中的#ifdef、#include和#define预处理命令。该阶段会生成一个中间文件.i,此阶段对于命令 #gcc -E hello.c -o hello.i
[root@localhost test]#cat hello.c
#include <stdio.h>
int main()
{
printf("Hello,World!\n");
return 0;
}
经过预处里后
[root@localhost test]#gcc -E hello.c -o hello.i
[root@localhost test]#cat hello.i |more
# 1 "hello.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "hello.c"
# 1 "/usr/include/stdio.h" 1 3 4
# 27 "/usr/include/stdio.h" 3 4
# 1 "/usr/include/features.h" 1 3 4
......
# 2 "hello.c" 2
int main()
{
printf("Hello,World!\n");
return 0;
}
可知在预处理阶段完成:
- 注释的删除
- 头文件的包含和插入
- #define定义的标识符替换
-hello.c文件由此变成了hello.i文件
2编译阶段
在编译阶段,输入的是中间文件.i,编译后生成汇编语言文件.s。这个阶段对应的gcc命令如下所示:#gcc -S hello.i -o hello.s
[root@localhost test]#gcc -S hello.i -o hello.s
[root@localhost test]#cat hello.s|more
.file "hello.c"
.section .rodata
.LC0:
.string "Hello,World!"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl $.LC0, %edi
call puts
movl $0, %eax
由此可知:
- 从.i 文件到.s文件,内容已经经过语法分析,词法分析变为汇编语言
3汇编到二进制机器码
在汇编阶段,将输入的汇编文件.s转换成二进制机器代码.o,这个阶段对应的gcc命令如下所示:# gcc -c hello.s-o hello.o
[root@localhost test]#ll
total 40
-rw-r--r-- 1 root root 70 May 21 16:28 hello.c
-rw-r--r-- 1 root root 16870 May 21 16:36 hello.i
-rwxr-xr-x 1 root root 8512 May 21 16:51 hello.o #可执行文件
-rw-r--r-- 1 root root 449 May 21 16:47 hello.s
[root@localhost test]#vim hello.o
3 ^@<98>^C@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^
^@^@^@^ @^@^C^@^O^@Ð^E@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@
^@^@^C^@^P^@ð^E@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^
@^@^C^@^Q^@(^F@^@^@ ^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^C^@^R^@^P
^N`^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^C^@^S^
@^X^N`^@^@^@^@^@^@^@^@^@^@^@^ @^@^@^@^@^@^C^
[root@localhost test]#./hello.o
Hello,World!
可知此阶段完成:
- 汇报语言到二进制的转换过程
链接阶段
在链接阶段,将输入的二进制机器代码文件*.o(与其他机器代码文件和库文件)汇集成一个可执行的二进制代码文件, 生成可执行文件 # gcc hello.o -o hello
[root@localhost test]#gcc hello.o -o hello
一次性编译
将上述4个步骤合并为一个步骤为如下一条gcc命令
[root@localhost test]#gcc hello.c -o hello
[root@localhost test]#./hello
Hello,World!