(原创)后置++在不同编译器中的行为
来源:互联网 发布:网络监控设备报价 编辑:程序博客网 时间:2024/05/15 11:33
int x = 0;
x = x++;
请问上述两行代码执行之后,x的值是什么?
有的同事说1,有的同事说0,究竟是什么呢,试试就知道。
试了三个编辑器,Inter,gcc和vc自带的cl。
Inter和gcc得出的结果都是0,vc得出的结果是1。
究竟哪个对呢?
让我们再看看那两行代码,第一行不用多说,把一个变量赋值为0,第二行是由两部分组成的,一部分是一个赋值语句,也就是 operator =(),一部分是后置++操作符,也就是operator ++()。
后置++的行为在c++中的标准中有明确的定义:首先,取出当前操作数(本例为x,下面均已x代替)的值,放到一个临时变量中,例如y,然后再把当前x的值加上1,然后返回那个临时变量的值,也就是y的值,这三个操作是一个原子操作,中间不能插入其他代码。所以,operator ++返回的是x未加上1之前的值。
这样答案就很明显了,按照c++标准,先取出x的值(例子中x的初值为0)放入y,x加上1,这时x的值是1,把operator++返回的y的值(也就是0)赋值给x,这时,x的值就从1变成0了,由此可见,Inter和gcc在这个操作符的实现比VC更符合c++的标准。
operator- -() 也是得到相似的结果。
下面列出VC和gcc所编译出来的这两行代码的汇编代码,可以更清楚的看出这两个编译器对后置操作符的实现。
先列出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的值放入临时变量,对x加1,返回临时变量的值,三步操作一口气完成,中间不夹其他操作。
总结:在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.
- (原创)后置++在不同编译器中的行为
- 后置++在不同编译器中的行为
- 前置(后置)++ /--与+/-在不同编译器下运算方式不同
- (原创)深入剖析:C++“多态性”在编译器中的实现
- assert 断言的不同编译器行为
- 原创-“差错控制”在数据链路层和运输层中的区别(不同)
- 栈变量被覆盖的问题在不同编译器中的表现,蛋疼的VC++
- std::async在gcc和vc不同编译器下的不同表现(可能会阻塞)
- C++与java在编译器上一个不同
- c99在不同编译器的实现情况
- 前置增量和后置增量在cout中的输出情况
- 在C语言算法中的前置++与后置++
- strcmp在不同系统/编译器下的结果不同
- 指针、++、--前置后置不同运算
- 用程序判断设置的是debug还是release以及assert在debug和release版本中的不同行为
- 设计模式:策略模式(对象的某个行为,在不同的场景中,有不同的实现算法)
- 程序在编译器(Compiler)中的执行流
- 一个在不同的编译器下会有不同结果的C++程序(程序本身只有四行)
- 集结号----昨天看地
- 第七章 类图
- 多媒体动画课件集
- (原创)OGRE主要渲染流程简介
- 英文星期月份缩写
- (原创)后置++在不同编译器中的行为
- 关于POJO
- AJAX ModalPopupExtender实现弹出窗体效果 结合UpdatePanel实现完全无刷新
- 简单了解下POJO和PO
- 把C++类成员方法直接作为线程回调函数
- Assignment2
- 在Solaris下使笔记本连接到投影仪的解决办法
- JasperReport初级教程(2.0.3)图文详解_绝对原创
- as中编译时加载外部图片的办法