您的位置:首页 > 编程语言

一段代码引起的思考-------printf

2012-03-08 17:39 204 查看
看一小段代码:

#include <stdio.h>

int main()

{

inta =5;

printf("%f\n" a);

return0;

}

在vc6.0和gcc中结果都是0.000000,为什么呢?

这得从int和float的转换说起,我们知道int是4 byte(32位),float也是4 byte,但是printf函数在将参数以单精度浮点数打印出来时,都是默认转换为双精度浮点数,也就是在在printf函数中,参数a是以32位入栈,但是打印取出时,却是按双精度取出64位,其中int的32位作为新的64位的低32位,高32位一般都为0。

在gdb中对程序进行反汇编:

ps:gcc中一般都有gdb,进入gcc,使用命令gcc –g test.c –o test,然后输入gdb test就可以进入gdb查看反汇编了。在gdb中,汇编指令格式默认是att的,使用命令set disassembly-flavor intel可以将反汇编格式设置成intel的,我将gdb中的汇编格式设置为Intel的,进入gdb后可以设置断点,可以单步执行,还可以将某个函数的汇编打印出来,从汇编中可以看到int确实是以32位入栈的。

ps:浮点数的表示方法



s为标志位,为1则浮点数为负,为0浮点数为正,exponent为幂位,后面的mantissa为有效位

下面再来看一个例子:

#include <stdio.h>

int main()

{

__int64 b;

b= 0x404B800000000000;

int a ;

a= 55;

printf("%f\n%f\n%f\n",a,b,);

printf("\n%f\n%f\n%f\n",b,a,);

return0;

}

这里说明一下C语言里面参数的入栈和出栈顺序,C方式参数入栈顺序(从右至左)的好处就是可以动态变化参数个数。通过栈堆分析可知,自左向右的入栈方式,最前面的参数被压在栈底。除非知道参数个数,否则是无法通过栈指针的相对位移求得最左边的参数。这样就变成了左边参数的个数不确定,正好和动态参数个数的方向相反,如上面第一个printf函数,入栈顺序为b,a,出栈顺序为a、b,a为我定义的一个64位的int变量,为了更好的说明结果,我将55.0的浮点数的64位16进制表示赋给了b,在gcc中运行结果为:

0.000000

0.000000

55.000000

0.000000

在第一个printf中,数据一这样的顺序入栈:0x40B80000、0x0、0x37,出栈后变为0x0000000000000037、0x........40B80000,........一般为0所以结果就为0.000000、0.000000,(有时最后一个可能是乱码)。

在这中间我也有很多不明白的地方,比如反汇编中,我找不到参数在printf中是怎么输出的,还有堆和栈的概念也不是很清晰,这次让我认识到自己的基础很不扎实,唉,小小叹息一下。

programming on the way
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: