之前囧哥曾经写过一个日志,讨论一个问题,就是在c/c++里面这个代码的结果
x = 1; x = x++;
执行后,x是2。这个结论还是比较显而易见的,不过编译器到底是怎么处理这段代码的呢?
我用 Fedora 15 自带的 gcc -S -O0 将 .c 编译成 .s 文件,来看看究竟编译器干了什么。
int x = 13; // 为了看汇编更方便,赋值13 x = x++;
被翻译成如下的汇编代码:
movl $13, -4(%rbp) ;x=13 addl $1, -4(%rbp) ;x++ movl $0, %eax popq %rbp
从汇编码来看,gcc 是这样理解x = x++的:
x = x; // 被优化掉了 x++;
也就是对于 int 这种 trivial 类型,= 的优先级高于后置++。 先赋值,再做后置++。
我们再来试几个代码:
第一组
int x=13; int y; y = x++;
翻译结果:
movl $13, -4(%rbp) ;x=13 movl -4(%rbp), %eax ;eax=x movl %eax, -8(%rbp) ;y=eax addl $1, -4(%rbp) ;x++ movl $0, %eax popq %rbp
————————————————–
第二组
int x=13; int y; x = y = x++;
翻译结果:
movl $13, -4(%rbp) ;x=13 movl -4(%rbp), %eax ;eax=x movl %eax, -8(%rbp) ;y=eax movl -8(%rbp), %eax ;eax=y movl %eax, -4(%rbp) ;x=y addl $1, -4(%rbp) ;x++ movl $0, %eax popq %rbp
————————————————–
第三组
int x=13; int y; y = ++x;
翻译结果:
movl $13, -4(%rbp) ;x=13 addl $1, -4(%rbp) ;++x movl -4(%rbp), %eax ;eax=x movl %eax, -8(%rbp) ;y=eax movl $0, %eax popq %rbp
————————————————–
从各个例子中可以看出,gcc 对于 int 这种 trivial 类型,认为 = 优先级高于后置++,低于前置++。
赋值先于后置++,后于前置++。
即使复杂点的例子x=((x++)+(y++)),相当于:
x=x+y;
x++;
y++;