仰望天上的光 发表于 2011-7-25 11:57:36

C语言谜题系列1

本帖最后由 仰望天上的光 于 2011-7-25 11:58 编辑

说明:为了增加各位鱼油的C语言基本功,我打算出一系列的C语言谜题(所有题目都是基于32位的C编译器,所以不保证在TURBO C下各个程序的行为),涉及到C语言的大部分阴暗面(目的不是打击C语言,而是让大家更了C语言,不至于陷入类似的陷进),每次首先解决谜题的鱼油获得全部的悬赏奖励,希望大家喜欢这个系列的活动。不废话了,本次的题目是这样的:以下程序将输出什么?并说明理由。


#include<stdio.h>
int main( void ){
int start = 2000000000;
int count=0;
float f;
for(f=start;f<start+50;++f)
    count++;
printf("%d\n",count);
return 0;
}

sinner 发表于 2011-7-25 11:57:37

我修改了一下代码,发现了一个问题!
代码如下:
#include<stdio.h>
int main( void )
{
int start = 2000000000;
int count=0;
float f;
int flag=0;
for(f=start;f<start+50;++f,flag++)
{

printf("\n%f\n",f);
count++;
if(flag>50)
break;

}

}其输出的结果:


大家看看,这for循环中,f的值是没有加1的,所以f一直小于start+50,所以,这个循环是死循环。因此,在VC++编译器里,上诉代码是没有输出结果的。{:5_109:}。

san千。 发表于 2011-7-25 12:20:10

坐等答案...~!

枭非鸟 发表于 2011-7-25 13:25:50

2000000048?

仰望天上的光 发表于 2011-7-25 14:38:21

枭非鸟 发表于 2011-7-25 13:25 static/image/common/back.gif
2000000048?

...主要是问为什么...至于答案,根本没有必要说...大家都有C语言的编译器吧???

最后的期待 发表于 2011-7-26 13:08:21

count加1后,f加1;这样循环50次。仰光,为什么要把f定义为float型呢?

仰望天上的光 发表于 2011-7-26 15:15:51

5楼分析得不对(出现在这里的题目绝对不会是像你想得那么简单)。
提示:把f定义为float类型而非int类型是这个题目的关键所在。

JX机械 发表于 2011-7-27 20:17:34

没返回值?。。。郁闷啊,看来道行太低了

吖查 发表于 2011-7-27 21:16:03

猜想:是不是int类型的2000000000转换为二进制,然后通过float类型在内存的表示方法,得出转换为float的二进制,然后再转回十进制,然后循环

zfzhuman123 发表于 2011-7-27 21:42:34

这个程序.............
我输出的结果是50,不过start为何值结果都为50;如果把f=start+50改为start+100结果就是100;
可是我用GDB调试,f的值竟然不变,count竟然无限大;
我纳闷的一点是,int类型的范围貌似没那么大,我编译环境int类型取值最大为32767;
可是令我奇怪的是200~~~~~竟然不溢出,你说把f设为float是问题所在,可是我改为int貌似也没问题;
很纠结,纠结这个过程!

JX机械 发表于 2011-7-27 22:14:53

zfzhuman123 发表于 2011-7-27 21:42 static/image/common/back.gif
这个程序.............
我输出的结果是50,不过start为何值结果都为50;如果把f=start+50改为start+100...

你用啥么编译器?有输出值?

JX机械 发表于 2011-7-27 22:48:38

我用的是vc6.0编译的,根本就没有输出,进入 了无限循环。我重看了一下c的数据类型和自己写了一些代码来调试,因为本人学c不久,所以说下我这个初学者的看法:float在电脑的储存是32位,其中8位是用来放符号和指数的,所以剩余的部分只有24位,不足以存放2000000000;则实际上只是2000000(这是我的猜想,我用打印语句时能把2000000000打印出来,但我用一些语句来进行比较大小时2000000050的float是小于int的),所以它一直小于start+50.便没有输出值。要是你把f的数据类型改成double或将start的值改成2000000就会得到50,这不知道这样的想法对不对,希望和大家交流下

仰望天上的光 发表于 2011-7-28 11:42:36

JX机械 发表于 2011-7-27 22:48 static/image/common/back.gif
我用的是vc6.0编译的,根本就没有输出,进入 了无限循环。我重看了一下c的数据类型和自己写了一些代码来调试 ...

很好,说得很接近了。

q369965658 发表于 2011-7-28 12:27:23

用一个int型的start来装这么大的数,结果肯定是未知的负数了,而用float类型的f 来装这2e溢出的数据是可以装下的,所以到循环的时候应该是个未知的很大的无限循环,所以在VC6下就是一直为黑屏而无输出。

仰望天上的光 发表于 2011-7-28 12:54:56

q369965658 发表于 2011-7-28 12:27 static/image/common/back.gif
用一个int型的start来装这么大的数,结果肯定是未知的负数了,而用float类型的f 来装这2e溢出的数据是可以装 ...

32位的int是可以装下这个数的。

q369965658 发表于 2011-7-28 13:44:10

仰望天上的光 发表于 2011-7-28 12:54 static/image/common/back.gif
32位的int是可以装下这个数的。

哦,32位的,其实答数你也说了一些了,既然你前面提到把f声明为float就是重点,就是告诉大家在由int转换为float时的精度会发生变化,而精度的变化上面的同学也已经说了,我也就不啰嗦了,换名话说,(float)2000000000 == 2000000050,因此表达式f 小于strat+ 50在第一次执行循环体之前就是不成立的,所以,循环体也就永远没有机会去运行,应该也就是输出0,而把它改成double,就没有精度丢失的问题了,会直接得出结果也就是50.

~疯子 发表于 2011-7-28 15:00:58

我是来偷东西的
哈哈
有偷到一点

JX机械 发表于 2011-7-28 16:55:19

呵呵,本来想放下的了,但看到LZ的回复,便忍不住再想了想这段代码。虽然我学c不久,但现在我肯定这个问题是出在这两种数据的不同的储存方式引发的。我自己写了些代码来测试发现float的2000000000和2000000050是等大的,我就查了下资料,又知道了单精度浮点数最多的十进制数的有效数字只有7位,超出的会四舍五入(也不知道这个和编译器有没关系),所以便会出现了我昨晚所说的情况,f一直小于start+50;则没有输出。呵呵,即使没答对,我还是学会到了许多东西,哈哈哈

仰望天上的光 发表于 2011-7-29 09:13:48

18楼很不错哦,这个题目有两个要点,你已经发现其中比较重要的那个了。

sinner 发表于 2011-7-29 17:21:02

仰望天上的光 发表于 2011-7-29 09:13 static/image/common/back.gif
18楼很不错哦,这个题目有两个要点,你已经发现其中比较重要的那个了。

另外的话float型的数据在内存的表现形式吧。如果是20亿,在内存里存放方式应该是:数符为+ ,小数部分为.2,指数部分为10。因为小数部分为.2所以占用2个位就能变现出来了。但加上1,20亿零1。这样的话,小数部分存放的书应该未.2000000001,这样的话,就需要32位来表达了。就会出现失精。这应该是C语言存在的缺陷吧。{:5_109:}
页: [1] 2 3
查看完整版本: C语言谜题系列1