首页 » 学习
一段Old Style C代码:不带类型声明的形参
2012-09-13
想想看下面一段程序的输出是什么?注意看sqr函数的形参部分,噢,它真的是合法的,只是模样有点古怪,这就是所谓的Old Style C(K&R C)。
double sqr(x) { return x * x; } int main() { printf("sqr(3.0): %f\n", sqr(3.0)); printf("sqr(3): %f\n", sqr(3)); return 0; }
在我的机器上,结果是:
sqr(3.0): 0.000000 sqr(3): 9.000000
如果没有为形参指定类型,结果是未定义的。试了几个编译器和机器,都采用将实参转为整数的方式,所以3.0变成了0。
可是,3.0转换为0的时候,发生了什么呢?让我们看看(VC生成的)汇编码:
printf("sqr(3.0): %f\n", sqr(3.0)); 0040EA08 push 40080000h 0040EA0D push 0 0040EA0F call @ILT+0(_sqr) (00401005) 0040EA14 fstp qword ptr [esp] 0040EA17 push offset string "sqr(*p++): %f\n" (00424fe0) 0040EA1C call printf (00401170) 0040EA21 add esp
在这段代码的头2行,我们看到了两个连续的压栈操作,似乎是想传2个参数进去。sqr只需要一个参数,所以只取了后进栈的参数,即0,所以上述程序结果是0.
那么,这个0,还有那个40080000h是怎么来的呢?这就牵涉到double类型的数据表示方法,以及小尾端的知识了。double有64位,从左往右,先是1位符号位,再是11位阶符,最后是52位尾数,其中阶要加上1023。所以3.0的浮点表示应该是4008-0000-0000-0000H,再转换为小尾端的顺序,就是0000-0000-0000-0840H,将3.0转换为int时,分成了2个int数据,头一个是0,后一个再转为正常顺序就是40080000H。
到这里,试着将sqr的声明改为:double sqr(x, y)
,同样传3.0进去,则x赋为0,y赋为40080000H。
这段代码改自P.J Plaucer的著作The Standard C Library 中第0章的习题。摘抄这本书的代码真有点不放心啊,Plaucer在前言里面的版权声明好吓人……不过,刚开始看到这段代码的输出,着实吓了一跳。也许这段古董代码的最大意义,就是告诫我们,不要使用未定义的编程方式吧。
« 二分图最大匹配的贪心解法及证明 小报栏 »
comments powered by Disqus