高手请进,一个绝对可以让编程初学者晕头转向的问题

vizwind 2001-11-30 10:08:08
这个问题真的让我晕头转向,请高手指点,送分20:

int a;
int i=2;

a= (++i) + (++i);

答案是8,我本来认为是7的,为什么?!!!
...全文
237 24 打赏 收藏 转发到动态 举报
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
vizwind 2001-12-02
  • 打赏
  • 举报
回复
我终于从另一个论坛找到了答案,我把它们引用过来与大家分享一下:
http://bbs.et8.net/bbs/showthread.php?s=&threadid=68982

----------------------引用------------------------------------------
這個問題真的很有意思。偶用 vc++ 6.0 sp5:




code:--------------------------------------------------------------------------------int main( void )
{
int b;
int i = 2;
b = (++i) + (++i) + (++i);
printf( "b=%d i=%d", b, i );
return 0;
}--------------------------------------------------------------------------------



這段 code 被 compile 成了:



code:--------------------------------------------------------------------------------.text:00401000 sub_401000 proc near ; CODE XREF: start+AF
.text:00401000 push 5
.text:00401002 push 0Fh
.text:00401004 push offset aBDID ; "b=%d i=%d"
.text:00401009 call sub_401020
.text:0040100E add esp, 0Ch
.text:00401011 xor eax, eax
.text:00401013 retn
.text:00401013 sub_401000 endp--------------------------------------------------------------------------------



明顯是 optimization 的後果,compille 的時候就把計算給做好了,但是算錯了,肯定是 bug。

但是關掉 optimization 以後:



code:--------------------------------------------------------------------------------.text:00401000 sub_401000 proc near ; CODE XREF: start+AF
.text:00401000
.text:00401000 i = dword ptr -8
.text:00401000 b = dword ptr -4
.text:00401000
.text:00401000 push ebp
.text:00401001 mov ebp, esp
.text:00401003 sub esp, 8
.text:00401006 mov [ebp+i], 2 ; i = 2;
.text:00401006 ; --------------------
.text:0040100D mov eax, [ebp+i] ;
.text:00401010 add eax, 1 ; ++i (i=3)
.text:00401013 mov [ebp+i], eax ;
.text:00401013 ; --------------------
.text:00401016 mov ecx, [ebp+i] ;
.text:00401019 add ecx, 1 ; ++i (i=4)
.text:0040101C mov [ebp+i], ecx ;
.text:0040101C ; --------------------
.text:0040101F mov edx, [ebp+i] ; edx := i + i (edx=8) **BUG**
.text:00401022 add edx, [ebp+i] ;
.text:00401022 ; --------------------
.text:00401025 mov eax, [ebp+i] ;
.text:00401028 add eax, 1 ; ++i (i=5)
.text:0040102B mov [ebp+i], eax ;
.text:0040102B ; --------------------
.text:0040102E add edx, [ebp+i] ; edx := edx + i (edx=13)
.text:0040102E ; --------------------
.text:00401031 mov [ebp+b], edx ; b := edx (b=13)
.text:00401031 ; --------------------
.text:00401031 ;
.text:00401034 mov ecx, [ebp+i] ; printf( "b=%d i=%d", b, i ); ...
.text:00401037 push ecx
.text:00401038 mov edx, [ebp+b]
.text:0040103B push edx
.text:0040103C push offset aBDID ; "b=%d i=%d"
.text:00401041 call sub_40104F
.text:00401046 add esp, 0Ch
.text:00401049 xor eax, eax
.text:0040104B mov esp, ebp
.text:0040104D pop ebp
.text:0040104E retn
.text:0040104E sub_401000 endp
--------------------------------------------------------------------------------



紅色部分就是 bug 所在。先兩次 ++i 然後才是 ( x ) + ( x ) ,所以結果比預期多了 1 。
-------------------------------------------------------------------------------
mahongxi 2001-12-01
  • 打赏
  • 举报
回复
极其赞同ssh_zy(电池正极)的观点,人家高手(哪位不知了)讲:

“我从来不记一些很容易从书本上查到的东西”
jacket3 2001-12-01
  • 打赏
  • 举报
回复
检验一下(++i)+(++i)+(++i)是否是15呢?
无为 2001-12-01
  • 打赏
  • 举报
回复
讨论这个没什么意义的,这和编译器有关的。估计写程序的时候,很少有人会这样干的吧。
benny80818 2001-12-01
  • 打赏
  • 举报
回复
无论是(++i)+(++i)

还是(++i)+(++i)+(++i)
(++i)+(++i)+(++i)+(++i)
(++i)+(++i)+(++i)+(++i)+(++i)

VC中总是想象值+1。
dog_dog 2001-12-01
  • 打赏
  • 举报
回复
太拘泥了
leepiaoping 2001-12-01
  • 打赏
  • 举报
回复
同意mzm100,在VC下的结果是8,应该是这个原因
mzm100 2001-12-01
  • 打赏
  • 举报
回复
a= (++i) + (++i);
本来第一个++I=3,第二个++i=4,可以在内存里,两者使用同一个地址,也就是3被4冲掉了,因此a=4+4=8;
zhouqiming 2001-12-01
  • 打赏
  • 举报
回复
搞懂这种东西,要看编译原理的,里面讲的还是蛮清楚的,也就是说,
和具体的编译器有关。这种东西考试肯定不会考,如果考,说明出题
的人水平有问题,或者见识太少。而且在编程中,即使知道能出个什么
样的结果,也不会有人写的。
算了,这个问题就到这里,给我点分吧。
BlackTooth 2001-12-01
  • 打赏
  • 举报
回复
这要看编译器的问题了。
sans 2001-12-01
  • 打赏
  • 举报
回复
VC是这样把下面的程序翻译成汇编语言的:
int a;
int i=2;

a= (++i) + (++i);

MOV EAX, 2 <=> int i=2;
INC EAX <=> (++i) 第一个,此时EAX = 3
INC EAX <=> (++i) 第二个,此时EAX = 4
ADD EAX, EAX <=> 中间的+号,于是a = EAX + EAX = 4 + 4 = 8

不同的编译器所翻译的结果不一样,实际上等于7也好,等于8也好均不错。在GNU C/C++中就有编译选项对此进行调整。
vizwind 2001-12-01
  • 打赏
  • 举报
回复
我也知道这个问题很无聊,真正编程没人这么做,但我去面试,有两次别人都问这个问题,看来天底下,无聊的人还是挺多的.

我觉得zhouqiming说的最有道理,所以20分就送给他了。

附:benny80818总结的规律是对的,我在VC下试过。
xtky_limi 2001-11-30
  • 打赏
  • 举报
回复
从不写这样和自己过不去的代码!!!!
Happy_Wawe 2001-11-30
  • 打赏
  • 举报
回复
研究这玩意,太孔已几了吧!
ssh_zy 2001-11-30
  • 打赏
  • 举报
回复
拘泥于这样的句子,就永远是个初学者
zhouqiming 2001-11-30
  • 打赏
  • 举报
回复
这个程序我在Linux的gcc下试过,在turbo c下也试过,当然,还有VC,结果不同的。
这是和编译器有关的,应该说不属于语言上的东西。
liqi 2001-11-30
  • 打赏
  • 举报
回复
我也不写这样和自己过不去的程序。
HeroRose 2001-11-30
  • 打赏
  • 举报
回复
这关系到编译器在作语义分析的动作了
各家的产品可能又不同的处理方式,
baifeng 2001-11-30
  • 打赏
  • 举报
回复
同意:A_Qiao()
A_Qiao 2001-11-30
  • 打赏
  • 举报
回复
初学者也没必要钻这个牛角尖
加载更多回复(4)

16,551

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Creator Browser
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧