深入理解计算机系统-之-数值存储(六)--以不同的方式窥视内存
浮點數(shù)寫,整數(shù)讀
好了知道了浮點數(shù)的存儲方式,那么我們的問題來了,如果我們定義了一個浮點數(shù),那么如果以整數(shù)的格式去讀取它,會發(fā)生什么奇妙的現(xiàn)象
代碼示例
我們對上一篇文章中修改main函數(shù)為如下形式
我們定義了變量float f = 9.0f, 然后用一個整形指針去讀它,由于32位機器上int和float類型的大小是一致的,不會存儲訪問越界(即使是64位機器,int也不一定為不是32位,因為這個不僅跟機器字長相關(guān),還跟編譯器的處理方式相關(guān))
float 9.0表示出來 =1001×2?0?=1.001×2?3??
階碼=3 +127 =130 =10000010B
| 0 | 10000010 | 00100000000000000000000 |
存儲起來就是0x41100000H
浮點數(shù)讀
第一種讀取方式:直接對這個浮點數(shù)按照整數(shù)方法讀取
這個不需要多說什么,存儲格式與讀取格式一致
第二種讀取方式:用pInt型指針按照浮點數(shù)格式讀取
首先,將0x00000009拆分,得到第一位符號位s=0,后面8位的指數(shù)E=00000000,最后23位的有效數(shù)字M=000 0000 0000 0000 0000 1001。
由于指數(shù)E全為0,所以符合上一節(jié)的第二種情況。因此,浮點數(shù)V就寫成:
V=(-1)^0×0.00000000000000000001001×2^(-126)=1.001×2^(-146)
顯然,V是一個很小的接近于0的正數(shù),所以用十進制小數(shù)表示就是0.000000。
整數(shù)讀
第一種方式,直接printf以”%d”輸出浮點數(shù)f
這種方式下,出現(xiàn)了一個奇妙的問題,我們的浮點數(shù)9.0f用%d輸出后,變成了0.0。
這是為什么呢。因為在C語言中浮點數(shù)默認為雙精度(double),除非指定F,但是printf打印時對于單精度浮點數(shù),仍然要轉(zhuǎn)換成雙精度浮點數(shù)然后打印,因此
- 1
- 1
會進行如下處理
單精度浮點數(shù):9.0F = 0 | 10000010| 00100000000000000000000
- 求出它的單精度內(nèi)存表示,
- 轉(zhuǎn)換為雙精度,有效位不足補0,
- 輸出低32位所表示的十進制數(shù)
總的來說,在打印一個浮點數(shù)時,一.浮點數(shù)轉(zhuǎn)換成雙精度 二. 打印低32位.
因此打印的結(jié)果始終為0
第二種方式,強制轉(zhuǎn)換后去讀取
將浮點數(shù)(單雙精度)轉(zhuǎn)換為整數(shù)時,將舍棄浮點數(shù)的小數(shù)部分, 只保留整數(shù)部分。將整型值賦給浮點型變量,數(shù)值不變,只將形式改為浮點形式, 即小數(shù)點后帶若干個0。
注意:賦值時的類型轉(zhuǎn)換實際上是強制的。
因此顯示的結(jié)果是9
第三種讀取方式:用一個int型的指針去讀取
這個也比較好理解,由于我們用了一個int行的指針去讀取
那么編譯器處理時會認為這個是一個int型的變量
回到前面float 9.0表示出來是
| 0 | 10000110 | 0110010001000000000 |
小端模式的存儲結(jié)構(gòu)為00001041,編譯器出來以后會·按字節(jié)進行整合,
存儲的int值其實是0x41100000H = 1091567616
第二次讀寫
接著我們用整形指針向f中寫入了數(shù)據(jù) *pInt = 9; 雖然我們看起來好像沒什么變化,但是其實寫入的數(shù)據(jù)已經(jīng)發(fā)生了很大變化,因為前面的兩篇博文我們已經(jīng)看到,整數(shù)和浮點數(shù)的存儲格式是有很大區(qū)別的。
這個操作其實是將一個單精度浮點數(shù)標識的9.0f的存儲格式,強制變成了整數(shù)9的存儲格式。
因此進行浮點數(shù)讀全為0(階碼為0)
而我們用pInt去按照整數(shù)讀取的時候,由于存儲格式本來就是整數(shù)的存儲格式,因此讀取出來是9
整數(shù)寫,浮點數(shù)讀
跟上一個例子相反,我們定一個int型變量,然后用float型的指針進行讀取
int main(void) {printf("%d == %d\n", sizeof(float), sizeof(int));int num = 9; /* num是整型變量,設(shè)為9 */float* pFloat = (float *)# /* pFloat表示num的內(nèi)存地址,但是設(shè)為浮點數(shù) */print_byte((void *)&num, sizeof(num));print_bit((void *)&num, sizeof(num));printf("the float : %f, %f\n", num, *pFloat); //以浮點視角看printf("the int : %d, %d\n", (int)num, *pFloat); //以整型視角看*pFloat = 9.0f; /* 將num的值改為浮點數(shù) */print_byte((void *)&num, sizeof(num));print_bit((void *)&num, sizeof(num));printf("the float : %f, %f\n", num, *pFloat); //以浮點視角看printf("the int : %d, %d\n", (int)num, *pFloat); //以整型視角看return EXIT_SUCCESS; }同樣我們這個代碼,用上面的分析就很簡單了。也不過是將一個浮點數(shù)的存儲格式,強制變成了整數(shù)的存儲格式而已
轉(zhuǎn)載:http://blog.csdn.net/gatieme/article/details/50709093
總結(jié)
以上是生活随笔為你收集整理的深入理解计算机系统-之-数值存储(六)--以不同的方式窥视内存的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 实战3--设计管理模块, 第4步, 新增
- 下一篇: 在eclipse里配置Android n