编译的详细过程
- 预编译
- 编译
- 汇编
- 链接
.h .c .cpp (源代码)------> .i (预处理后源代码) ----------> .S (汇编代码)--------->.O (中间文件) ----------> .out .exe
上面四个步骤都在干什么
- 预编译
删除注释
添加行号和文件标识
执行编译器命令
删除所有#define 并进行展开
展开include(递归展开)
处理所有预编译命令#if #ifndef等
- 编译
语义分析 : 判断表达式是否有意义
词法分析 : 将源代码的字符序列分割成一系列记号
语法分析 : 对记号进行语法分析没产生语法树
代码优化
生成汇编语言
- 汇编
将汇编语言翻译成机器能看懂的机器语言
- 链接
将中间文件连接成可执行文件
举例
#include <stdio.h>
#define PI 3.14
int main() {
// 这是注释
int num = 10 + PI;
printf("Hello World\n");
return 0;
}
gcc -E test.cc -o test.i
变成
... // 展开的include文件
extern void funlockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
# 868 "/usr/include/stdio.h" 3 4
# 2 "test.c" 2
# 5 "test.c"
int main() {
int num = 10 + 3.14;
printf("Hello World\n");
return 0;
}
gcc -S test.i -0 test.S
汇编代码
.file "test.c"
.text
.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
subq $16, %rsp
movl $13, -4(%rbp)
leaq .LC0(%rip), %rdi
call puts@PLT
movl $0, %eax
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0"
.section .note.GNU-stack,"",@progbits
gcc -c test.S -o test.o
生成目标文件
gcc test.o -o test.out