一、首先说明下自增运算符与编译器的中间代码有关:
++x 表示取x的地址,增加它的内容,然后把值放在寄存器中;x++ 则表示取x地址,把它的值 装入寄存器中,然后增加内存中x的值。
二、现看下面的例子:
5 int i=-1,j=-1;
6 int x,y;
7 x=(i++)+(i++)+(i++);
8 y=(++j)+(++j)+(++j);
9 printf("%d,%d/n",x,y);
结果为 -3,4
原因:c语言对于这种运行的处理不是把i++或++j一个一个分开算的。 对于x=(i++)+(i++)+(i++); 因为是后置运算符,他是先完成运算,然后再执行三次i++的。所以x=-3,i=2 而y=(++j)+(++j)+(++j);一样是先算三个++i然后再整个表达式,但是汇编级只能实现两个数相加,不能实现三个数相加,所以先是(++i)+(++i) 先i=1,然后1+1=2,接着执行2+(++i) 那么先i=2 ,然后2+2=4。
备注:x=(i++)+(i++)+(i++); 不加括号也是一样的,根据优先级,但是y表达式涉及到 非左值的运算,所以要加括号
转载部分:假如,int x=20; x=(x++);(你会发现与x=x++等价,这是一种未定义的写法)
可以看到编译器对x=(x++) 语句生成的汇编代码如下:
下面解释这段汇编代码的含义。其中“ebp-20h”是变量x的存储地址。
第一行将x的值,这里是数字“20”放入寄存器edx,
第二行将edx里的值放回到存储变量x的地址内,注意在这里先进行了赋值操作,
第三行将x的值“20”放入eax寄存器,这时x的值还是20,因为先前没有经过任何算术运算,
第四行将eax寄存器内的值加一,
第五行将eax寄存器内的值放入存储变量x的地址内。
到这里我们已经能够很清楚的看到了在执行x=(x++) 语句时不管赋值运算符(=)和自增运算符(++)的优先级如何程序都是先将表达式的右值x先做赋值操作,由于是自身赋值给自身,这时x的值还为20。最后才将x的值进行的增1操作。所以最后x的值是21,而不是20。
这个特性其实在例如:y=z++;这样的表达式中也是适用的,c++在这里也是像上例一样的先进行赋值再做的增一运算。只不过按照运算符优先级的原则运算出来的结果和实际的结果是一样的,所以这个特性没有明显的表达出来。
最后像x=((y++) + (x++));的语句也是先把x+y的值(这里假设x=20,y=0)先赋给x,然后x,y再各自做增一运算,最后x=21。