日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

C语言程序设计 | 整型、浮点型在内存中的存储方式

發布時間:2024/4/11 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C语言程序设计 | 整型、浮点型在内存中的存储方式 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

整型在內存中的存儲

一個變量的創建要在內存中開辟空間,空間的大小是根據不同的類型決定的。
那數據在數據在所開辟的空間中是如何存儲的呢?
首先我們要了解三個概念:

原碼 反碼 補碼

計算機中的有符號數有三種表示方法,即原碼、反碼和補碼。
三種表示方法均有符號位數值位兩部分,符號位都是用0表示正,用1表示負,而數值為的三種表示方法各不同。
原碼:
直接將二進制按照正負數的形式翻譯成二進制就可以。
反碼:
將原碼的符號位不變,其他位依次按位取反就可以得到了。
補碼:
反碼+1就可以得到補碼。

正數的原碼、反碼、補碼相同。
我們所看到的二進制是原碼的形式,而它們在內存中是以補碼的形式存放的。
下面來舉幾個例子

int i = 10;int j = -8;

對于I,它的原碼是:
00000000 00000000 00000000 0001010
而它所存放在內存是補碼,而正數的補碼即是它的原碼,所以存放形式為:
00000000 00000000 00000000 0001010

對于j, 它的原碼是:
10000000 00000000 00000000 0001000
它的反碼為:
11111111 11111111 11111111 1110111
它的補碼為:
11111111 11111111 11111111 1111000
它存放在內存中就是以上面的補碼形式存放的。

為什么我們要以這種補碼的形式存放在內存中呢?

在計算機系統中,數值一律用補碼來表示和存儲。原因在于,使用補碼,可以將符號位和數值域統一處理。同時,加法和減法也可以統一處理(CPU只有加法器)此外,補碼和原碼相互轉換,其運算過程是相同的,不需要額外的硬件電路

那如何用加法器來實現減法呢?
因為負數用補碼來存放
所以例如
i = 1-1
我們可以把它看成
i = 1 + (-1)
1的補碼為
00000000 00000000 00000000 0000001
-1的補碼為
11111111 11111111 11111111 1111111
兩者相加得到
00000000 00000000 00000000 0000000
這就是我們想要的結果,同理除法和乘法也可以用加法器來實現。

下面我們要了解不同字節的數據類型之間的計算方式。
如果我們要將一個高字節的數據存放在一個低字節的類型中,例如將int型存放在char型中,我們要用到一種方法,叫做截斷

為什么是截斷?
下面舉一個例子

char a = 1;

對于1,它在內存中存放的形式是這樣的:

而我們將它存放在僅僅只有一個字節的char型中,它就會被截斷為最低位的那個字節中的數據

即:00000001

那如果我們想要將一個低字節的數據類型用高字節的方式輸出呢?
例如:

#include<stdio.h> int main() {char a = -128;printf("%u",a); return 0; }

它的輸出結果為

為什么我們會得到這樣一個奇怪的數據呢?
在這里,我們還要引入一個概念,叫做整型提升

那么,什么是整型提升?
對于一個低字節的數據類型,如果我們將它轉換為高字節的數據類型,我們需要將它的二進制位補充到對應的字節,補充的規則是當數據為有符號數的時候,補符號數,如果為無符號數,補0.

對于上面的代碼,我們就來分析一下。
首先整型-128的原碼為
10000000 00000000 00000000 1000000
反碼
11111111 11111111 11111111 0111111
補碼
11111111 11111111 11111111 10000000
然后將其截斷,存放在char中的二進制位為
10000000
同時我們將其以無符號整型的方式輸出,所以需要先將其提升為整型,它的符號位為1,則前面全部補1
11111111 11111111 11111111 10000000
而因為我們輸出的是無符號的整形,所以我們將上面的二進制補碼直接當作原碼,所以我們就得到了這個巨大的數字。

浮點型在內存中的存儲

#include<stdio.h> int main() {int n = 1;float *p = (float *)&n;printf("n = %d\n",n);printf("*p = %f\n\n",*p);*p = 1.0;printf("n = %d\n",n);printf("*p = %f\n",*p);return 0; }

對于上面這段代碼,它的運行結果是:

*明明n 和 p在內存中是同一個數,為什么浮點數和整型的解讀結果會差別這么大?要理解這個結果,一定要搞懂浮點數在計算機內部的表示方法

根據國際標準IEEE(電氣和電子工程協會)754,任意一個二進制浮點數V可以表示成下面的形式:

  • (-1)^ S * M * 2 ^ E
  • (-1)^ S表示符號位,當S=0,V為整數。當S=1,V為負數。
  • ?M表示有效數字,大于等于1,小于2
  • ?2 * E表示指數位

那如何理解呢?首先我畫個圖來大概描述一下

這個是二進制前八位代表的數值,當我們要取到小于1的數時,我們可以想到,用2的負數次方來表示,于是可以這樣表示

所以十進制的5.0,我們將其用二進制表示就是101.1,相當于(-1) ^ 0 x 1.01 x 2 ^ 2。
用上面的格式的話 S = 0,M = 1.01,E = 2。
那它在內存中又是怎么存放的呢?

IEEE 754 規定 : 對于32位的單精度浮點數,最高的1位是符號位S,接著的8位是指數E,剩下的23位為有效數字M
如下圖:

對于64位的雙精度浮點數,最高的1位是符號位S,接著的11位是指數E,剩下的52位為有效數字M
這里的圖我就不畫了,可以參考上面的自行腦補。

在之前有一條性質,M表示有效數字,大于等于1,小于2,也就是說,這個M必為1,原先的寫法為1.xxxxxxxx,而我們可以將這個1省略掉,因為它是一個固定值,我們可以直接寫為后面的xxxxxxx,這樣我們就可以節約一位,就可以表示24位的有效數字,而當我們要讀取的時候,再將這個第一位的1給加上去。

而指數E,它的規則就顯得有些復雜

E作為一個無符號的整數,這表示著如果E為8位,它的取值范圍為0-255(2^8 -1)。如果E為11位,它的取值范圍為0-2047.但是我們知道,科學計數法中的E時可以出現負數的,**所以IEEE 754規定,存入內存時E的真實值必須再加上一個中間數,**對于8位的E,這個中間數是127(2 ^ (8-1)-1) ;對于11位的E,這個中間值是1023.比如,2^10的E是1-,所以保存成32位浮點數時,必須保存成10+127=137,即10001001。

而當我們將指數E從內存中取出的時候,存在三種情況。

E不全為0或者不全為1

這時,浮點數就采用下面的規則表示,即指數E的計算值減去中間數127或1023,得到真實值,再將有效數字M前面加上第一位的1。
比如:0.5的二進制為0.1,用上述表示法則為(-1)^ 0 * 1.0 * 2 ^ (-1),階碼為-1+127 = 126.
126二進制表示為
01111110
尾數1.0去掉常值1,剩下一個0,補齊0到23位,所以二進制表示形式位:
0 01111110 00000000000000000000000

E全為0

這時,指數E等于1-127(1023)得到真實值,有效數字M不再加上第一位的1,而是還原為0.xxxxxx的效數,這樣做是為了±0及無限趨近于0的數字

E全為1

這是,如果有效數字M全為0,表示±無窮大(正負取決于符號位S)

總結

以上是生活随笔為你收集整理的C语言程序设计 | 整型、浮点型在内存中的存储方式的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。