好难的C习题啊!!请牛人看看!!(不牛的不要来!)

hotice 2004-04-04 11:48:34
小弟学习C语言,用的教材是西安电子科技大学出版社马鸣远编著的《程序设计与C语言》,104页中的第22题:

22.指出下面程序的执行结果。
#include<stdio.h>
main()
{
int s=0,i=1,j=10;
while(i--&&j--,s+=2,j++<15);
printf("%d\n",i+j+s);
return 0;
}

用TurboC2.0编译运行出来的结果是19,实在是不懂!何解???

先给100分,不够再加!各位大侠看看!
...全文
40 47 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
47 条回复
切换为时间正序
请发表友善的回复…
发表回复
w3guy 2004-04-06
  • 打赏
  • 举报
回复
这个程序在VC下不是死循环,只是时间很长。试想一下,循环约4294967296×4次需要多少时间。
在tc 下循环约65536×4次,时间要短的多。
fbmsf 2004-04-06
  • 打赏
  • 举报
回复
上面vc 编译的,是死循环。
fbmsf 2004-04-06
  • 打赏
  • 举报
回复
int main(int argc, char* argv[])
{

_asm nop
_asm xor eax,eax
_asm mov eax,1
_asm mov eax,2
_asm xor eax,eax

int s=0,i=1,j=10;
while(i--&&j--,s+=2,j++<15);
printf("%d\n",i+j+s);
return 0;
}

asm 代码:






00401000 fn_00401000:
00401000 56 push esi
00401001 90 nop
00401002 33C0 xor eax,eax
00401004 B801000000 mov eax,1
00401009 B802000000 mov eax,2
0040100E 33C0 xor eax,eax
00401010 33C9 xor ecx,ecx
00401012 BA01000000 mov edx,1
00401017 B80A000000 mov eax,0Ah
0040101C loc_0040101C:
0040101C 8BF2 mov esi,edx
0040101E 4A dec edx
0040101F 85F6 test esi,esi
00401021 7401 jz loc_00401024
00401023 48 dec eax
00401024 loc_00401024:
00401024 83C102 add ecx,2
00401027 8BF0 mov esi,eax
00401029 40 inc eax
0040102A 83FE0F cmp esi,0Fh
0040102D 7CED jl loc_0040101C
0040102F 03C2 add eax,edx
00401031 03C1 add eax,ecx
00401033 50 push eax
00401034 6830604000 push 406030h
00401039 E812000000 call fn_00401050
0040103E 83C408 add esp,8
00401041 33C0 xor eax,eax
00401043 5E pop esi
00401044 C3 ret
逍遥的心 2004-04-06
  • 打赏
  • 举报
回复
无聊的题目
haizhiyu 2004-04-06
  • 打赏
  • 举报
回复
题目很好,但真的比较难,建议将int 改为char
条件语句:i--&&j--因为是and,所以当i!=0时,需执行另一个条件,即执行j--;如果i==0则可判断条件语句(i--&&j--为非),不执行j--,此时整个j--和j++执行结果是j=j+1。
calmton 2004-04-06
  • 打赏
  • 举报
回复
这个程序在VC下死循环,在TC下算出是19,但是在TC下如果while循环体内有代码的话就会陷入死循环。我是这样理解的,在TC下,如果循环体内没有代码,while()只取逗号表达式最右边表达式的值,左边及中间的表达式不去计算,而如果循环体内有代码,那么整个逗号表达式里边的表达式都要进行运算,刚进行完j++又进行j--,当然死循环了。而在VC下,不管循环体内有没有代码,都要计算逗号表达式里的所有表达式,j++刚进行完就进行j--,所以就死循环了。
实际应用中不允许出现这样的代码,但是这种代码好像有助于了解各个公司编译器的实现差别。
小弟菜鸟,愿倾听各位大侠真知灼见!
王国凡 2004-04-06
  • 打赏
  • 举报
回复
有点无聊,这样的程序的确不好理解。

1.当 i 为 0 时,下一个 j 才会增 1
2.这里,i 不断减 1 ,直到溢出又回到了 0 时,j 增 1
3.当两个条件都为假(j++ < 15 为假,i--&&j-- 为假)时,就跳出来。

My god! TC 是 16 位的,还有心情等溢出,等结果,在 32 位 C++ 里就没心情等了,如果要是 64 位,128 位,那...
fzd999 2004-04-06
  • 打赏
  • 举报
回复
32位VC编译器,结果是一个超级长循环,你可以花一个晚上来执行:)
while(i--&&j--,s+=2,j++<15); // 这个语句比较变态
可以翻译成这样的形式:
while(TRUE)
{
if ( (i-- != 0) && (j-- != 0)
&& ( (s += 2) != 0 )
&& (j++ < 15) )
{
break;
}
}

不过,这样的形式,还是TMD很难懂。
vollin 2004-04-05
  • 打赏
  • 举报
回复
关于时间差异的问题,我们要知道调试时与实际运行时是不同的,所谓单步,实际上是运行一行的程序,而且每次运行完了之后除了程序用的时候外,还要在代码中定位,这是显示刷新的速度与CPU速度是无法匹配的。所以才会有差异,而你直接运行所用的时间你可以测一下,绝对是一样的。
hotice 2004-04-05
  • 打赏
  • 举报
回复
呵呵!感谢各位大侠,其实这道题真的是我的小弟在教材上看到的,要我帮他解释,我想到的原因跟各位说的差不多。但是我在调试的时候还发现了这样一个现象。
当我把代码改成以下这个样子:
001 #include<stdio.h>
002 main()
003 {
004 int s=0,i=1,j=10;
005 int x=0,y=0,z=0;
006 while(i--&&j--,s+=2,j++<15){x=i;y=j;z=s;}
007 printf("%d\n",i+j+s);
008 return 0;
009 }
当代码是上面这个样子的时候,在Turboc2.0中调试时,使用F7单步,在第6行一下就过了,并且可以监测到x,y,z 的值分别是-1、4、16。
当我把代码改成下面这个样子:
001 #include<stdio.h>
002 main()
003 {
004 int s=0,i=1,j=10;
005 int x=0,y=0,z=0;
006 while(i--&&j--,s+=2,j++<15)
007 {
008 x=i;
009 y=j;
010 z=s;
011 }
012 printf("%d\n",i+j+s);
013 return 0;
014 }
当我把代码改成上面这个样子,单步时Turboc2.0的编译器会在第8行到第10行反复运行很长的时间,直到溢出后得到19。
如果说溢出我还想得通,那么这两段的运行差异就让我很奇怪了,怎么会是这样呢?TC的编译器究竟是怎么做的?

看到大家说了这么多,我很感谢,其实我把这个题发出来还有一个意思,就是想问问这本书的作者或编者,书出来后你自己调试过这段代码吗?或者是印刷错了,但是为什么没有看到勘误呢?要知道,你们的书是给一群对计算机程序充满向往而刚刚起步学习的年轻学生,他们对于计算机程序的理解和判别都十分有限。教科书对于学生是有相当强的引导作用的,我想问问你们是想引导什么?是要他们以后在编程工作中利用“溢出”来得到正确结果吗?话说到这里,也想奉劝各位,对待年轻学生的教育,对待编书、出书,谨慎!谨慎!
coollang 2004-04-05
  • 打赏
  • 举报
回复
说变态到谈不上,其实对于C语言来说,如果不提供答案的话,反而是这样的题更有利于理解。
其实这个题主要有三方面
1、逗号表达式
2、短路条件表达式
3、整型溢出
如果想理解最好的办法就是看他的汇编输出!
showjancn 2004-04-05
  • 打赏
  • 举报
回复
关键是要看(j++<15)是真还是假,当然你试试
while(i--&&j--,s+=2,j++<15,0)
while(i--&&j--,s+=2,j++<15,1)
之后,你就会一目了然了!!
showjancn 2004-04-05
  • 打赏
  • 举报
回复
其实这个问题很简单!!
因为while()的原型是while(bool),
所以这个程序主要的问题是在这bool上面,bool为1则运行while,bool为0则跳过。
所以这里只是对(i--&&j--,s+=2,j++<15)这个整体进行判断,对它进行强制(隐式)类型转换后的值是false还是true的问题!
当然有一点必须说清的在VC中对于多个串的判断是以最后一项的结果为准(当然不同编译器可能有问题),所以while(i--&&j--,s+=2,j++<15)就相当于
do
{
i--&&j--;
s+=2;
}while(j++<15)
所以j--之后,又j++,j的值终没变,当然肯定小于15,因此(j++<15)始终为true
因此列循环!!
simouse 2004-04-05
  • 打赏
  • 举报
回复
可以申请变态程序了
lfyang 2004-04-05
  • 打赏
  • 举报
回复


UP
lgs666 2004-04-05
  • 打赏
  • 举报
回复

好变态的C习题啊!!
hotice 2004-04-04
  • 打赏
  • 举报
回复
呵呵!我也知道平时不会用!但是,这个题会是什么样呢?
PDD123 2004-04-04
  • 打赏
  • 举报
回复
奇怪了,我怎么从来都没有写过这样的while语句
flyelf 2004-04-04
  • 打赏
  • 举报
回复
这应该是一个死循环
keansun 2004-04-04
  • 打赏
  • 举报
回复
如果你在工作中编出这样的程序,老板肯定给你开了,中国人就是考试的天才,出考题也是天才,^_^
加载更多回复(27)

16,548

社区成员

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

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

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