
正文
c语言中fldcpy函数 c语言fib函数
提示:扫一扫查出行【扫一扫了解最新限行尾号】
复制提示
C语言中为何整型变量以实型变量输出为0?
1、整形数和浮点数在内存中c语言中fldcpy函数的存储格式和布局不同(理解浮点数的内存布局和表示方式,请参考c语言中fldcpy函数:)
2、printf在进行参数入栈时是根据实参的类型进行入栈,而不是根据格式化字符中指定的类型,具体入栈过程如以下所示。所以造成入栈实参的类型和实际函数使用的类型不匹配(关键是所占内存的大小不同),所以在具体的解析中就会出现如题所说的结果,因为整形的内存布局在被解析为浮点数时会非常小,因为整形本来是4个字节存储,而被解析为8个字节的浮点数,所以所得的值会非常小,正如浮点数的的表示:非规格化:当E的二进制位全部为0时,N为非规格化形式。
注意,此时小数点左侧的隐含位为0。 为什么e会等于(1-bias)而不是(-bias),这主要是为规格化数值、非规格化数值之间的平滑过渡设计的。后文我们还会继续讨论。
有了非规格化形式,我们就可以表示0了。把符号位S值1,其余所有位均置0后,我们得到了 -0.0; 同理,把所有位均置0,则得到 +0.0。非规格化数还有其他用途,比如表示非常接近0的小数,而且这些小数均匀地接近0,称为“逐渐下溢(gradually underflow)”属性。
下面贴出两段反汇编代码,解析参数如何入栈:
printf("%f",45);
00405028 mov esi,esp
0040502A push 2Dh
0040502C push offset _ORDER_SERVER_ADDRESS-0ACh (43F2ACh)
00405031 call dword ptr [__imp__printf (43C124h)]
00405037 add esp,8
printf("%f",d);(d为整形变量)
00405028 mov esi,esp
0040502A mov ecx,dword ptr [d]
0040502D push ecx
0040502E push offset _ORDER_SERVER_ADDRESS-0ACh (43F2ACh)
00405033 call dword ptr [__imp__printf (43C124h)]
00405039 add esp,8
0040503C cmp esi,esp
0040503E call _RTC_CheckEsp (439760h)
double a=5,c;
float b;
int d=0x40a00000,y=6;
int *p;
char s=5;
p=d;
b=(float)a;
printf("%f,%f,%f,%f,%f,%f,%d",b,c,(float)d,s,(float)s,y,y);
00405028 mov esi,esp
0040502A mov ecx,dword ptr [y]
0040502D push ecx
0040502E mov edx,dword ptr [y]
00405031 push edx
00405032 movsx eax,byte ptr [s]
00405036 mov dword ptr [ebp-34h],eax
00405039 fild dword ptr [ebp-34h]
0040503C sub esp,8
0040503F fstp qword ptr [esp]
00405042 movsx ecx,byte ptr [s]
00405046 push ecx
00405047 fild dword ptr [d]
0040504A sub esp,8
0040504D fstp qword ptr [esp]
00405050 sub esp,8
00405053 fld qword ptr [c]
00405056 fstp qword ptr [esp]
00405059 fld dword ptr [b]
0040505C sub esp,8
0040505F fstp qword ptr [esp]
00405062 push offset _ORDER_SERVER_ADDRESS-0C4h (43F2ACh)
00405067 call dword ptr [__imp__printf (43C124h)]
0040506D add esp,30h
00405070 cmp esi,esp
00405072 call _RTC_CheckEsp (439780h)
相关问答
Q1: 在C语言中的各种赋值是如何转换的?
关于赋值操作,你可以查看一下博客的内容,初学者不用理解底层汇编的实现机制,有点晦涩,随着自己的进步可以进一步的深入底层查看其实现原理
1 代码案例
iint main()
{
int n,m;
char ch;
float f = 12.12;
double d=121.111;
n = f; //单精度浮点赋值给整数
m =d; //双精度浮点赋值给整数
ch = n; //整数赋值给字符值
ch = f; //浮点赋值给字符值
f = d; //整数变量赋值给浮点变量;
return 0;
}
2 以上代码调试运行对应的汇编代码分析
101: float f = 12.12; //单精度浮点赋值:占用4个字节,需要1条汇编指令实现
源代码对应1条汇编指令:
00401C78 mov dword ptr [ebp-10h],4141EB85h
102: double d=121.111; //双精度浮点赋值:占用8个字节,需要2条汇编指令实现
源代码对应2条汇编指令:
00401C7F mov dword ptr [ebp-18h],9FBE76C9h
00401C86 mov dword ptr [ebp-14h],405E471Ah
103: n = f; //单精度浮点赋值给整数
源代码对应3条汇编指令:
00401C8D fld dword ptr [ebp-10h]
00401C90 call __ftol (004232cc)
00401C95 mov dword ptr [ebp-4],eax
104: m =d; //双精度浮点赋值给整数
源代码对应3条汇编指令:实际的类型转换通过调用内部C运行时接口函数__ftol来实现类型转换。
00401C98 fld qword ptr [ebp-18h]
00401C9B call __ftol (004232cc) //调用__ftol函数(对应15条汇编指令,见下面3描述)
00401CA0 mov dword ptr [ebp-8],eax
105: ch = n; //整数赋值给字符值
源代码对应2条汇编指令:
00401CA3 mov al,byte ptr [ebp-4]
00401CA6 mov byte ptr [ebp-0Ch],al
106: ch = f; //浮点赋值给字符值
源代码对应3条汇编指令:
00401CA9 fld dword ptr [ebp-10h]
00401CAC call __ftol (004232cc)
00401CB1 mov byte ptr [ebp-0Ch],al
107: f = d; // 整数转换为浮点数,源代码对应2条汇编指令:
00401CB4 fld qword ptr [ebp-18h]
00401CB7 fstp dword ptr [ebp-10h]
3 赋值涉及的__ftol函数对应的汇编指令:
__ftol 函数对应以下16条指令:
004232CC push ebp
004232CD mov ebp,esp
004232CF add esp,0F4h
004232D2 wait
004232D3 fnstcw word ptr [ebp-2]
004232D6 wait
004232D7 mov ax,word ptr [ebp-2]
004232DB or ah,0Ch
004232DE mov word ptr [ebp-4],ax
004232E2 fldcw word ptr [ebp-4]
004232E5 fistp qword ptr [ebp-0Ch]
004232E8 fldcw word ptr [ebp-2]
004232EB mov eax,dword ptr [ebp-0Ch]
004232EE mov edx,dword ptr [ebp-8]
004232F1 leave
004232F2 ret
4 C运行库(Run-Time Library)存在的原因
4.1 定义(摘自《软件调试》,张银奎)
当编译器在将高级语言编译到第几语言的过程是,因为高级语言中的某些比较负责的运算符(如不同的类型转换)要对应比较多的低级语言指令(如汇编、机器指 令),为了防止这样的指令段多次重复出现在目标代码中(造成目标码过大),编译器通常将这些指令段封装为函数,然后将高级语言的某些操作翻译为函数调用。
C标准定义了标准C函数,C++标准定义了C++标准类库,这些库通常被称为支持库,这些库是程序编译运行的必要条件,因此支持库也称为运行库(Run-Time Library).
VC提供了C和C++运行库。
4.2 例子
1)如上面例子,VC编译器通常将 n =f( n :整数,f:浮点数)这样的赋值编译为调用__ftol函数;
2)VC编译器也将new ,delete 操作符编译为对malloc和free函数调用(可以通过单步调试运行,反汇编单步跟着call 指令观察分析验证!)
5 总结
1)通过以上分析,不同类型变量转换,是编译程序在编译程序过程中,将操作转换编译成调用运行库函数来实现的。
2)一般程序设计过程中,不是必要情况下,不要频繁使用不同类型互相转换的操作,特别是涉及到循环运算、性能的优化的程序!
Q2: c语言如何把float型转化为char型
如果
x
是
float
型,c
是
char
型,这样就可以把
类型转换
:
c
=
(char)
x;
所谓转换是这样的。例如:
float
x
=
65.1;
char
c;
c
=
(char)
x;
这样
c
里存的就是
65,即字符
'A'。
补充回答:
还有另外一种“转换”,就是
Arvin
2010-11-06
14:08
所说的,不过不是
float
型转换成
char
型,而是把
float
型的
数字转换
成为“字符型数组”的表达方式。这种转换最简单的方法就是借用
里的
sprintf
函数,把实数打印到数组里。
例如:
float
x
=
65.1;
char
a[20];
sprintf(a,
"%g",
x);
这样子,数组
a
里就会保存字符串
"65.1",即
a[0]
=
'6';
a[1]
=
'5';
a[2]
=
'.';
a[3]
=
'1';
a[4]
=
'\0';
不知道楼主要的,是哪一种转换。请选择满意的答案采纳。如有疑问,欢迎追问。
c语言中fldcpy函数的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于c语言fib函数、c语言中fldcpy函数的信息别忘了在本站进行查找喔。







