之前囧哥曾经写过一个日志,讨论一个问题,就是在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++;