王垠主页上的一个例子的解释,不是很明白。。。。。。。。

C、C++和Java语言
回复
头像
gre_linewer
帖子: 180
注册时间: 2006-11-22 10:57
送出感谢: 0
接收感谢: 0
联系:

王垠主页上的一个例子的解释,不是很明白。。。。。。。。

#1

帖子 gre_linewer » 2007-04-23 17:28

一个叫 1.c,内容是
#include<stdio.h>
int main()
{
float f=23.45;
printf("main: %f\n", f);
t1(f);
}

另一个是 2.c,内容是:
#include<stdio.h>
void t1(float f)
{
printf("t1: %f\n", f);
}
用 GCC 编译这两个程序到一起:
gcc 1.c 2.c
运行得到结果:
main: 23.450001
t1: 2.000000
gcc 编译如果不加 -Wall 选项就不给任何错误提示!可是它却吧 t1() 的 prototype 缺省当成了接受整型参数!
想问下:
它怎么就吧 t1() 的 prototype 缺省当成了接受整型参数?就算接受整型参数,也应该是23啊???
Ubuntu 8.04
IBM R52-18465DC
CPU:PM 1.73Ghz DDR2:768MB 533Mhz
INTEL 915GM/915PM
ATI Mobility Radeon X300 64MB
40G SATA
isarc
帖子: 15
注册时间: 2006-12-26 16:22
送出感谢: 0
接收感谢: 0
联系:

Re: 王垠主页上的一个例子的解释,不是很明白。。。。。。。。

#2

帖子 isarc » 2007-04-23 23:22

gre_linewer 写了:一个叫 1.c,内容是
#include<stdio.h>
int main()
{
float f=23.45;
printf("main: %f\n", f);
t1(f);
}

另一个是 2.c,内容是:
#include<stdio.h>
void t1(float f)
{
printf("t1: %f\n", f);
}
用 GCC 编译这两个程序到一起:
gcc 1.c 2.c
运行得到结果:
main: 23.450001
t1: 2.000000
gcc 编译如果不加 -Wall 选项就不给任何错误提示!可是它却吧 t1() 的 prototype 缺省当成了接受整型参数!
想问下:
它怎么就吧 t1() 的 prototype 缺省当成了接受整型参数?就算接受整型参数,也应该是23啊???

代码: 全选

#include<stdio.h>
extern void t1(float f);
int main()
{
float f=23.45;
printf("main: %f\n", f);
t1(f);
} 
即可
skyboy
帖子: 31
注册时间: 2005-10-26 22:18
送出感谢: 0
接收感谢: 0

#3

帖子 skyboy » 2007-04-24 16:18

唉,一遇到这种稍微有点难度的问题,
我就暴露菜鸟的本质了。

不过可以这样解释:

1,首先应该知道这个诡异的现象是由于没有对t1函数进行声明引起的。
如果在main函数调用t1之前,声明t1的函数原型,就不会有这种问题。

2,隐式声明。
在调用一个函数之前,没有见到对此函数的声明,不知其原型。
则把第一次调用当作隐式声明。
并且返回值为int。(C里面整型的地位比较特殊。)
至于函数参数,float要转换成double。

3,按照 IEEE 754 标准,float占4个字节,一位符号位,8位指数,23位尾数。
而double占8个字节,1个符号位,11位指数,52位尾数。
(具体的,自己再查资料吧)

这样,23.45,在内存中,float表示为41bb 999a,
即0100 0001 1011 1011 1001 1001 1001 1010
作为参数入栈时,
转换成double,
只需:
符号位不变: 0-->0
指数部分值不变,但增长为11位:1000 0011 -> 100 0000 0011
尾数原来23位,补上29个0,得到:0111 0111 0011 0011 0011 0100 0000 0000 0000 0000 0000 0000 0000
得到的double在内存中是:4037 7333 4000 0000

然后,在t1函数中,从栈中取参数,由于它认为自己的参数是float类型,
故只读了4个字节。读到4000 0000。
即0100 0000 0000 0000 0000 0000 0000 0000
按float处理,第一位0,正数,
接下来8位1000 0000,即移码的1,即指数为1。
后面全0,
即float值被认为是:1.0*10^1 (二进制),即2.0
所以输出为2.0.
HP nx 6120,
cpu CM 1.5G,
chip 915GM,
memory 512M,
harddisk 40G 5400rpm。

ubuntu 7.04 feisty,
with beryl, etc.
skyboy
帖子: 31
注册时间: 2005-10-26 22:18
送出感谢: 0
接收感谢: 0

#4

帖子 skyboy » 2007-04-24 16:21

这是我第一次打那么多01。
真累,
几十年前,
计算机刚刚出现时,
那些牛人就是整天对着数不清的001011么?
HP nx 6120,
cpu CM 1.5G,
chip 915GM,
memory 512M,
harddisk 40G 5400rpm。

ubuntu 7.04 feisty,
with beryl, etc.
头像
gre_linewer
帖子: 180
注册时间: 2006-11-22 10:57
送出感谢: 0
接收感谢: 0
联系:

#5

帖子 gre_linewer » 2007-04-24 17:19

多谢
Ubuntu 8.04
IBM R52-18465DC
CPU:PM 1.73Ghz DDR2:768MB 533Mhz
INTEL 915GM/915PM
ATI Mobility Radeon X300 64MB
40G SATA
头像
gre_linewer
帖子: 180
注册时间: 2006-11-22 10:57
送出感谢: 0
接收感谢: 0
联系:

#6

帖子 gre_linewer » 2007-04-24 17:21

多谢
Ubuntu 8.04
IBM R52-18465DC
CPU:PM 1.73Ghz DDR2:768MB 533Mhz
INTEL 915GM/915PM
ATI Mobility Radeon X300 64MB
40G SATA
回复

回到 “C/C++/Java”