深度剖析數據在內存中的存儲(整型和浮點型)

我們知道一個變量的創建是要在內存中開闢空間的,空間的大小是根據不同的類型而決定的,而且不同的類型也影響着我們看待內存空間的視角。
比如:int a = 20,float b= 5.0
接下來我們看看數據在所開闢的類型中是如何存儲的?

整型在內存中的存儲

整型家族

char
unsigned char,signed char
short
unsigned short,signed short
int
unsigned int,signed int
long
unsigned long,signed long

原碼、反碼、補碼

  • 原碼: 直接將二進制按照正負數的形式翻譯成二進制即可
  • 反碼: 原碼的符號位(用0表示正,用1表示負)不變,其他位依次按位取反
  • 補碼: 反碼加1

對整型來說:數據存放內存中其實存放的是補碼(正數的原反補碼都相同)
原因是:1.符號位和數值位可以統一處理。2.加法和減法可以統一處理(CPU只有加法器)。3.補碼與原碼相互轉換,運算過程也是相同的,不需要額外的硬件電路。
16進制存放在這裏插入圖片描述
我們發現對a和b分別存放的是補碼,但順序有點不對勁,這又是爲什麼呢?

大端和小端

  • 大端存儲模式:數據的低位保存在內存的高地址中,數據的高位保存在內存的低地址中。

  • 小端存儲模式:數據的地位保存在內存的低地址中,數據的高位保存在內存的高地址中。
    內存中從左到右依次是由低地址到高地址
    在這裏插入圖片描述

  • 設計一個程序來判斷當前機器的字節序

#include <stdio.h>
int check()
{
	int x = 1;
	return (char)x;//強制類型轉換,保留最低位的一個字節。
}

int main()
{
	int ret = check();
	if (ret == 1)
	{
		printf("小端");
	}
	else
	{
		printf("大端");
	}
	return 0;
}

下面程序輸出什麼?

練習題1

#include<stdio.h>
int main()
{
    char a = -1;                          
    signed char b = -1;
    unsigned char c = -1;
    printf("a=%d\nb=%d\nc=%d\n", a, b, c);
    return 0;
}

運行結果

a=-1,b=-1,c=255

解析
唯一的不同點就是a,b,c 的類型不同,輸出結果卻有如此大的差異。
將-1(int)2進製爲11111111 11111111 11111111 11111111的值賦給char類型時首先發生的時整型的截斷,char接收到的只是-1最低位的一個字節2進製爲:1111 1111
printf輸出時以%d的形式輸出cahr類型會發生整型的提升,發生提升時,有符號數高位補符號位,無符號數高位補0。
有符號數a的補碼爲:11111111 11111111 11111111 11111111
有符號數b補碼爲:11111111 11111111 11111111 11111111
無符號數c補碼爲:00000000 00000000 00000000 11111111

練習題2

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

運行結果

4294967168

解析
首先根據a的原碼寫出a的補碼
根據整型的截斷,char接收到的是a最低位的一個字節 2進製爲:1000 0000
打印時%u爲無符號整型,則cahr a發生整型提升 無符號數a的補碼爲:11111111 11111111 11111111 10000000無符號數的補碼=原碼。

練習題3

#include<stdio.h>
#include<string.h>
int main()
{
    char a[1000];
    int i;
    for (i = 0; i < 1000; i++)
    {
        a[i] = -1 - i;
    } 
    printf("%d\n", strlen(a));
    return 0;
}

運行結果

255

解析
strlen求字符串長度,實質找的是’\0’的位置,即a = 0時。
i從0開始到999,a[i]接收值從-1到-1000,char a [i]會發生整型的截斷,低位一個字節爲 0000 0000時,即求出字符串長度。(注意‘\0’不計入字符串長度)
i = 0時 -1截斷之後爲:1111 1111
i = 1時 -2截斷之後爲:1111 1110
i = 2時 -3截斷之後爲:1111 1101
當達到 0000 0000時i = 255(下標),則字符串長度爲0到254,輸出255。

浮點型在內存中的存儲

浮點型家族

float,double,long double

浮點型存儲的例子

在這裏插入圖片描述
n和*pFloat在內存中明明是同一個數,爲什麼整數和浮點數的解讀結果會差別這麼大?要理解這個結果,我們首先要搞懂浮點數在計算機內部的表示方法。

根據國際標準IEEE(電氣和電子工程協會)754,任意一個二進制浮點數v可以表示爲下面的形式:(-1)^s*M*2^E
(-1)^s表示符號位,當s=0時,v爲正數;當s=1時,v爲負數;
M表示有效數字,大於等於1小於2;
2^E表示指數位;

舉例來說:
在這裏插入圖片描述
如何把十進制的浮點型轉換爲二進制呢?
例如十進制0.5轉化爲二進制爲0.1
在這裏插入圖片描述
float a = 5.0存儲如下 (-1)^0*1.01*2^2
在這裏插入圖片描述
對於雙精度浮點型 S(1bit) E(11bit) M(52bit)

因爲整型存儲和浮點存儲的規則不同,所以在輸出時纔會產生如此大的差別。
回到剛開始的問題:

整型9: 0000 0000 0000 0000 0000 0000 0000 1001還原爲浮點型
由浮點存儲規則得 指數E全爲0,E=1-127,有效數字M不再加1,而是表示爲0.xxxxx,浮點數V=(-1)^0*0.00000000000000000001001*2^-126=1.001*2^-146,所以用十進制小數表示爲0.000000

浮點型9.0用二進制表示爲1001.0
V=(-1)^0*1.001*2^3,S=0,M=1.001,E=3+127=130,存儲爲0 10000010 001 0000 0000 0000 0000 0000,還原爲10進製爲1091567616

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章