探究float类型参数的传递方式

今天周老师在群里发了一段代码,如下:

[cpp]  view plain  copy
  1. int _tmain(int argc, _TCHAR* argv[])  
  2. {  
  3.     int i = 15;  
  4.     float m = (float)i;  
  5.     printf("%d\n",m);  
  6.     return 0;  
  7. }  

并告知输出为0, 运行并且如此。查看反汇编代码如下

[cpp]  view plain  copy
  1. int _tmain(int argc, _TCHAR* argv[])  
  2. {  
  3. 00F51000 55                   push        ebp    
  4. 00F51001 8B EC                mov         ebp,esp    
  5. 00F51003 83 EC 08             sub         esp,8    
  6.     int i = 15;  
  7. 00F51006 C7 45 FC 0F 00 00 00 mov         dword ptr [i],0Fh    
  8.     float m = (float)i;  
  9. 00F5100D DB 45 FC             fild        dword ptr [i]    
  10. 00F51010 D9 5D F8             fstp        dword ptr [m]    
  11.     printf("%d\n",m);  
  12. 00F51013 D9 45 F8             fld         dword ptr [m]  
  13. 00F51016 83 EC 08             sub         esp,8   
  14. 00F51019 DD 1C 24             fstp        qword ptr [esp]  
  15. 00F5101C 68 F4 20 F5 00       push        offset ___xi_z+34h (0F520F4h)    
  16. 00F51021 FF 15 A0 20 F5 00    call        dword ptr [__imp__printf (0F520A0h)]    
  17. 00F51027 83 C4 0C             add         esp,0Ch    
  18.     return 0;  
  19. 00F5102A 33 C0                xor         eax,eax    
  20. }  
  21. 00F5102C 8B E5                mov         esp,ebp    
  22. 00F5102E 5D                   pop         ebp    
  23. 00F5102F C3                   ret    


请注意标红的两句,明明传递的float类型,怎么需要八个字节呢? 莫非传递float类型就是这样吗?于是我又写了个测试子函数

[cpp]  view plain  copy
  1. #include "stdafx.h"  
  2.   
  3. float fun(float f)  
  4. {  
  5.     return f+1;  
  6. }  
  7.   
  8. int _tmain(int argc, _TCHAR* argv[])  
  9. {  
  10.     int i = 15;  
  11.     float m = (float)i;  
  12.     float y = fun(m);  
  13.     printf("%d\n",m);  
  14.     return 0;  
  15. }  


其对应的反汇编代码为

[cpp]  view plain  copy
  1. int _tmain(int argc, _TCHAR* argv[])  
  2. {  
  3. 00B71020 55                   push        ebp    
  4. 00B71021 8B EC                mov         ebp,esp    
  5. 00B71023 83 EC 0C             sub         esp,0Ch    
  6.     int i = 15;  
  7. 00B71026 C7 45 F8 0F 00 00 00 mov         dword ptr [i],0Fh    
  8.     float m = (float)i;  
  9. 00B7102D DB 45 F8             fild        dword ptr [i]    
  10. 00B71030 D9 5D F4             fstp        dword ptr [m]    
  11.     float y = fun(m);  
  12. 00B71033 51                   push        ecx  
  13. 00B71034 D9 45 F4             fld         dword ptr [m]   
  14. 00B71037 D9 1C 24             fstp        dword ptr [esp]  
  15. 00B7103A E8 C1 FF FF FF       call        fun (0B71000h)    
  16. 00B7103F 83 C4 04             add         esp,4    
  17. 00B71042 D9 5D FC             fstp        dword ptr [y]    
  18.     printf("%d\n",m);  
  19. 00B71045 D9 45 F4             fld         dword ptr [m]    
  20. 00B71048 83 EC 08             sub         esp,8    
  21. 00B7104B DD 1C 24             fstp        qword ptr [esp]    
  22. 00B7104E 68 F4 20 B7 00       push        offset ___xi_z+34h (0B720F4h)    
  23. 00B71053 FF 15 A0 20 B7 00    call        dword ptr [__imp__printf (0B720A0h)]    
  24. 00B71059 83 C4 0C             add         esp,0Ch    
  25.     return 0;  
  26. 00B7105C 33 C0                xor         eax,eax    
  27. }  
  28. 00B7105E 8B E5                mov         esp,ebp    
  29. 00B71060 5D                   pop         ebp    
  30. 00B71061 C3                   ret    

请注意标红的汇编代码,调用fun函数时传递float类型使用了4字节,这才符合预期,但是调用printf时为何传递的8字节呢?终于baidu到这么一句话:

浮点数作为变参函数的参数时需要转换为双精度浮点值

这才揭晓了原因,原来float作为变参函数的参数需要转换为双精度浮点值(重要的话重复3遍)。

知道了这些,就不难理解本文开头的程序输出为0了, float (15) 转成双精度浮点数后,高位4字节为0,且此高4位和%d对应,故输出为0.

PS:不清楚自己分析的对不对,欢迎各路神仙留言指正。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值