编译器的工作主要就是帮人们减轻负担,随着更高级语言的出现,编译器可以帮助人们做出更好的判断。除了保证实现从高级语言到机器语言的翻译之外,编译器可以进行各种优化。
看一下这段代码的结果:
#include <stdio.h>
int main(){
int i = 3;
int sum;
sum = i++ + ++i ;
printf("sum is %d.\n",sum);
}
结合汇编来看看前自增和后自增的区别到底是怎么造成的。
0000000000400526
400526: 55 push %rbp
400527: 48 89 e5 mov %rsp,%rbp
40052a: 48 83 ec 10 sub $0x10,%rsp
40052e: c7 45 f8 03 00 00 00 movl $0x3,-0x8(%rbp) // i = 3
400535: 8b 45 f8 mov -0x8(%rbp),%eax // %eax = 3
400538: 8d 50 01 lea 0x1(%rax),%edx // %edx = 4
40053b: 89 55 f8 mov %edx,-0x8(%rbp) // i = 4
40053e: 83 45 f8 01 addl $0x1,-0x8(%rbp) // i = 5
400542: 8b 55 f8 mov -0x8(%rbp),%edx // %edx = 5
400545: 01 d0 add %edx,%eax // %eax += %edx
400547: 89 45 fc mov %eax,-0x4(%rbp)
可以看到后自增对应的汇编是lea,使用寄存器保存自增前的值;而前自增对应的则是直接对内存进行加。
编译器就是要将人们比较容易理解和学习的语言翻译成机器语言:
- 扫描 (词法分析)
- Parsing (语法分析)
- 类型检查 (语义分析)
- 优化
- 代码生成