博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
浮点数类型转换的及其内存模型
阅读量:6815 次
发布时间:2019-06-26

本文共 4288 字,大约阅读时间需要 14 分钟。

先看一段测试code:

void  do_test() {    unsigned int uValue = 0xC1480000;    printf("uValue = %u,%d,%x,&uValue = %p\n",uValue,uValue,uValue,&uValue);    float fValue1 = (float) uValue;    printf("fValue1 = %f,&fValue1 = %p, *((unsinged int*)&fValue1) = %x\n",fValue1,&fValue1,*((unsigned int*)&fValue1));    float fValue2 = *((float*) &uValue);    printf("fValue2 = %f,&fValue2 = %p, *((unsinged int*)&fValue2) = %x\n",fValue2,&fValue2,*((unsigned int*)&fValue2));}

它的运行结果为:

uValue = 3242721280,-1052246016,c1480000,&uValue = 0xbe99b59cfValue1 = 3242721280.000000,&fValue1 = 0xbe99b5a0, *((unsinged int*)&fValue1) = 4f414800fValue2 = -12.500000,&fValue2 = 0xbe99b5a4, *((unsinged int*)&fValue2) = c1480000

 

首先第一段uValue:

它的16进制表达方式也就是内存里面的值为0xC1480000;

将数据0xC1480000表示成unsigned int,它的值是3242721280;

将数据0xC1480000表示成int,它的值是-1052246016。

 

第二段fValue1:

它的值是从uValue强转而来的;

它的内存里面的值是0x4F414800,也就是说float fValue1 = (float) uValue;这种强转会改变内存里的值;

而这个0x4F414800表示成float,它的值是3242721280.000000。

 

第三段fValue2:

它的内存值是uValue的内存值拷贝而来的,是0xC1480000

而是0xC1480000表示成float,它的值是-12.5,也就是说float fValue2 = *((float*) &uValue);的赋值方式不会改变内存值。

 

我们从会变得角度看看上面的几个赋值过程:

000010e4 <_Z7do_testv>:    10e4:       b57f            push    {r0, r1, r2, r3, r4, r5, r6, lr}    10e6:       ab06            add     r3, sp, #24    ; 第一段    10e8:       4919            ldr     r1, [pc, #100]  ; (1150 <_Z7do_testv+0x6c>)    10ea:       481a            ldr     r0, [pc, #104]  ; (1154 <_Z7do_testv+0x70>)    10ec:       f843 1d0c       str.w   r1, [r3, #-12]!    10f0:       460a            mov     r2, r1    10f2:       9300            str     r3, [sp, #0]    10f4:       4478            add     r0, pc    10f6:       460b            mov     r3, r1    10f8:       f7ff ec0e       blx     918 
; 第二段 10fc: ed9d 7a03 vldr s14, [sp, #12] 1100: eef8 7a47 vcvt.f32.u32 s15, s14 1104: a806 add r0, sp, #24 1106: ee17 2a90 vmov r2, s15 110a: eef7 0ae7 vcvt.f64.f32 d16, s15 110e: f840 2d08 str.w r2, [r0, #-8]! 1112: edcd 7a01 vstr s15, [sp, #4] 1116: 9000 str r0, [sp, #0] 1118: 480f ldr r0, [pc, #60] ; (1158 <_Z7do_testv+0x74>) 111a: ec53 2b30 vmov r2, r3, d16 111e: 4478 add r0, pc 1120: f7ff ebfa blx 918
; 第三段 1124: f8dd c00c ldr.w ip, [sp, #12] 1128: ab06 add r3, sp, #24 112a: 480c ldr r0, [pc, #48] ; (115c <_Z7do_testv+0x78>) 112c: ee00 ca10 vmov s0, ip 1130: f843 cd04 str.w ip, [r3, #-4]! 1134: 4478 add r0, pc 1136: 9300 str r3, [sp, #0] 1138: eeb7 1ac0 vcvt.f64.f32 d1, s0 113c: f8cd c004 str.w ip, [sp, #4] 1140: ec53 2b11 vmov r2, r3, d1 1144: f7ff ebe8 blx 918
1148: b007 add sp, #28 114a: f85d fb04 ldr.w pc, [sp], #4 114e: bf00 nop 1150: c1480000 1154: 00000105 1158: 000000fb 115c: 00000122

第二段中的vcvt.f32.u32指令就是u32转成float的,而vcvt.f64.f32是float转double的。

那第二段为什么会出现vcvt.f32.u32呢?因为print中的%f表示的是double类型,所以fValue1就强制转换成double类型了。

同样,第三段中,也有vcvt.f64.f32,但第三段不会有vcvt.f32.u32。

 

因此浮点数的强制类型转换,会带来内存值的改变,而这个内存值的改变正是用vcvt指令进行的。

它的转换依据是IEEE标准,可以参考

 

0xC1480000 -> 1100 0001 0100 1000   0000 0000 0000 0000

符号位:1 表示是负数

指数位:100 0001 0 = 130

小数位: 100 1000   0000 0000 0000 0000

 

 

运算方法:

小数位前面加个1和点‘.’

1.100 1000   0000 0000 0000 0000

指数位值减去127,如130-127=3,表示小数点右移3个位,得:

1100 .1000   0000 0000 0000 0000

小数点前面的数1100 = 1*(2^3)+1*(2^2)+0*(2^1)+0*(2^0) = 12

小数点后面的数1000   0000 0000 0000 0000 = 1*(2^-1)+0*(2^-2)+0*(2^-3)+... = 1*(2^-1) = 0.5

加上符号位后,它的值就是-12.5

 

同理:

0x4F414800 -> 0100 1111 0100 0001 0100 1000 0000 0000

符号位:0 表示是正数

数位:100 1111 0 = 158

小数位: 100 0001 0100 1000 0000 0000

运算方法:

小数位前面加个1和点‘.’

1.100 0001 0100 1000 0000 0000

指数位值减去127,如158-127=31,表示小数点右移31个位,得:

1100 0001 0100 1000 0000 0000 0000 0000.

明显,这个值就没有小数点后面的数了,

二进制1100 00001 0100  1000 0000 0000 0000 0000转换成十进制就是3242721280

 

转载于:https://www.cnblogs.com/YYPapa/p/6854371.html

你可能感兴趣的文章
ajax(异步页面动态刷新)
查看>>
关于JQuery的选择器
查看>>
Java和C++的区别
查看>>
git工作区和暂存区
查看>>
C函数调用与栈
查看>>
SQL优化小技巧
查看>>
UVALive 4850 Installations 贪心
查看>>
JS 中刷新页面的方法
查看>>
励志帝马云是不是你的财富导师?
查看>>
力扣算法题—088合并两个有序数组
查看>>
APP和web设计区别
查看>>
三层fragment嵌套,接口回调方式
查看>>
sfcapd服务新增nfdump安装
查看>>
Node.js:DNS模块的使用
查看>>
C指针函数中的局部变量返回
查看>>
获取总页数和分页的公用方法
查看>>
【cocos2d-js官方文档】四、基础数据类型
查看>>
【IIS错误】IIS各种错误
查看>>
LeetCode题解 | 215. 数组中的第K个最大元素
查看>>
DL4NLP —— 序列标注:BiLSTM-CRF模型做基于字的中文命名实体识别
查看>>