(原创)后置++在不同编译器中的行为

来源:互联网 发布:网络监控设备报价 编辑:程序博客网 时间:2024/05/15 11:33

int  x = 0;

x = x++;

 

请问上述两行代码执行之后,x的值是什么?

有的同事说1,有的同事说0,究竟是什么呢,试试就知道。

试了三个编辑器,Intergccvc自带的cl

Intergcc得出的结果都是0vc得出的结果是1

究竟哪个对呢?

让我们再看看那两行代码,第一行不用多说,把一个变量赋值为0,第二行是由两部分组成的,一部分是一个赋值语句,也就是 operator =(),一部分是后置++操作符,也就是operator ++()

后置++的行为在c++中的标准中有明确的定义:首先,取出当前操作数(本例为x,下面均已x代替)的值,放到一个临时变量中,例如y,然后再把当前x的值加上1,然后返回那个临时变量的值,也就是y的值,这三个操作是一个原子操作,中间不能插入其他代码。所以,operator ++返回的是x未加上1之前的值。

这样答案就很明显了,按照c++标准,先取出x的值(例子中x的初值为0)放入yx加上1,这时x的值是1,把operator++返回的y的值(也就是0)赋值给x,这时,x的值就从1变成0了,由此可见,Intergcc在这个操作符的实现比VC更符合c++的标准。

operator- -() 也是得到相似的结果。

下面列出VCgcc所编译出来的这两行代码的汇编代码,可以更清楚的看出这两个编译器对后置操作符的实现。

先列出VC的,我试了vc.net 2003和最新的vc.net 2008,得到的结果是一样的。

     int x = 0;

0041138E  mov         dword ptr [x],0 ; x赋初值为0

     x = x++;

00411395  mov         eax,dword ptr [x]  ; 取出x的值,放入eax

00411398  mov         dword ptr [x],eax  ; 取出eax的值,放入x中,这两句对应的c代码是x = x,可以看出,先执行了赋值操作。

0041139B  mov         ecx,dword ptr [x] ; 取出x的值,放入ecx

0041139E  add         ecx,1 ; ecx中的值加1

004113A1  mov         dword ptr [x],ecx ; ecx中的值赋值给x,以上三句执行的是c代码更像是++x

以上就是VC编译出来的代码,按这样的代码执行,得到的结果当然是1,从上面的汇编代码可以看出,在VC的实现中,如果operation ++ operator = 一起出现时,先执行的是operator =

接下来,我们看看gcc编译出的汇编代码。

movl $0, -4(%ebp) ; x初始化为0

movl -4(%ebp), %edx ; x的值放入到edx中,edx的值就会作为opeator ++的返回值

leal -4(%ebp), %eax ; 取出x的地址,放入eax

incl (%eax) ; eax中的值加1,实际上就是对x的值加1,执行之后,x=1

movl %edx, -4(%ebp) ; edx的值赋值给x,执行之后,x=0

由此可见,gcc的实现完全符合c++标准中的实现,把x的值放入临时变量,对x1,返回临时变量的值,三步操作一口气完成,中间不夹其他操作。

总结:在operator ++ operator = 一起出现的时候,VC的实现先执行 operator =,再执行 operator ++,不符合c++标准。而gcc的实现就是符合c++标准的。当然,在实际开发时不应写这种晦涩难懂的代码,一是你不能保证这种代码在各种平台上的实现是一致的,二是维护起来也麻烦。

最后摘抄一段c++ iso文档的后置++的描述。

The value obtained by applying a postfix ++ is the value that the operand had before applying the operator.[Note: the value obtained is a copy of the original value ] The operand shall be a modifiable lvalue. The type of the operand shall be an arithmetic type or a pointer to a complete object type. After the result is noted, the value of the object is modified by adding 1 to it, unless the object is of type bool, in which case it is set to true.

原创粉丝点击