x=x++;

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