1. 程式人生 > >浮點數類型轉換的及其內存模型

浮點數類型轉換的及其內存模型

unsigned 表達 value 及其 ebe sig 會有 裏的 -1

先看一段測試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 = 0xbe99b59c
fValue1 = 3242721280.000000,&fValue1 = 0xbe99b5a0, *((unsinged int*)&fValue1) = 4f414800
fValue2 = -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 <[email protected]>
    ; 第二段
    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 <[email protected]>
    ; 第三段
    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 <[email protected]>
    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標準,可以參考http://blog.csdn.net/demon__hunter/article/details/3566232

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

浮點數類型轉換的及其內存模型