1. 程式人生 > >整形資料在記憶體中的儲存

整形資料在記憶體中的儲存

整型資料在記憶體中的儲存,是一個值得細細體會的問題,千萬不要把它忽視了!!!下面我們來詳細談一談:

什麼是整形?

整形有:char     short      int       long       long long  

各種整形又分為:signed  (有符號型,沒有寫 signed 這個關鍵字的型別預設是有符號型別:例如上一行的型別都是有符號型別)

                             unsigned(無符號型別)

各種型別的範圍:

認識類型範圍前先看看兩個密訣:1000 0000    1後面7個0,則表示:2的7 次方  即128

                                                       0111 1111     0後面7個1,則表示:2的7次方減1  即128-1=127

同時請記住邊緣資料:2^7 = 128                 2^15 = 32768               2^31 = 2147483648

                                    2^8 = 256                 2^16 =  65536              2^32 = 4294967296

                                    2^10 = 1024             

好,現在我們來看看具體型別的範圍,注意:下面帶括號意思是書寫的時候可以省略,系統會自動預設有

(signed)  char  (有符號char整形, 32位機器佔一個位元組8bit位) 

最小值 1000 0000   [2^7](-128) 每個型別的這種形式都是有符號數的最小值

最大值  0111 1111   [2^7-1] (127)    此時最大值要是再加一,結果就是-128

 

unsigned char (無符號char整形, 32機器佔一個位元組8bit位) 

最小值 0000 0000 (0) 

最大值  1111 1111   [2^8-1] (255)    此時最大值要是再加一,結果就是0

 

(signed)  short  (有符號短整形, 32位機器佔兩個位元組16bit位) 

最小值 1000 0000 0000 0000   [2^15](-32768) 每個型別的這種形式都是有符號數的最小值

最大值  0111 1111  1111 1111    [2^15-1] (32767)    此時最大值要是再加一,結果就是-32768

 

unsigned short (無符號短整形, 32機器佔兩個位元組16bit位) 

最小值 0000 0000 0000 0000(0) 

最大值  1111 1111  1111 1111    [2^16-1] (65535)    此時最大值要是再加一,結果就是0

 

 

(signed)  int  (有符號整形, 32位機器佔四個位元組32bit位) 

最小值 1000 0000 0000 0000  0000 0000 0000 0000 [2^31](- 2147483648) 每個型別的這種形式都是有符號數的最小值

最大值  0111 1111  1111 1111   1111  1111  1111  1111 [2^31-1] (2147483647)    此時最大值要是再加一,結果就

是-2147483648

 

unsigned int (無符號整形, 32機器佔四個位元組32bit位) 

最小值 0000 0000 0000 0000 0000 0000 0000 0000(0) 

最大值  1111 1111  1111 1111   1111 1111  1111  1111 [2^32-1] (4294967296)    此時最大值要是再加一,結果就是0

 

此時附加一個內容,資料在記憶體中的儲存是大端還是小端?

小端:資料的低位  存放在記憶體的低地址  稱為小端儲存方式   :簡稱小(低位)小(低地址)小(小端)

 大端:資料的高位  存放在記憶體的高地址  稱為大端儲存方式

上一張圖來解釋清楚:

 

看一下具體記憶體的儲存方式(下圖是小端儲存)

 

 

現在讓我們來看看關於大小端的筆試題:

//方法一

#include <stdio.h>
#include <windows.h>

int check_sys()
{
	int i = 1;  //記憶體中 :00 00 00 01  或  01  00  00  00
	return (*(char *)&i);//int型資料地址型別是  int * ,所以現在要強轉成char * ,
	                    //因為解引用時我們要按照 char 型別讀取1個位元組。
}

int main()
{
	int ret = check_sys();//直接用一個函式判斷
	if (ret == 1)
	{
	    printf("小端儲存\n");
	}
	else
	{
	    printf("大端儲存\n");
	}
	system("pause");
	return 0;
}

//方法二(利用聯合體enum)

#include <stdio.h>
#include <windows.h>

int check_sys()
{
	union
	{
	    int i;
	    char c;
	}un;//宣告並定義
	un.i = 1;
	return un.c;
}

int main()
{
	int ret = check_sys();//直接用一個函式判斷
	if (ret == 1)
	{
	    printf("小端儲存\n");
	}
	else
	{
	    printf("大端儲存\n");
	}
	system("pause");
	return 0;
}

 

現在我們來總結一下三個結論!!!重要結論!!!

1   往記憶體中存資料時,直接按照型別大小把資料的 "補碼" 存進記憶體。(正數原碼==反碼==補碼,負數原碼取反加1 == 補碼)

2   CPU去記憶體取資料時,遇到整形提升時,看原來資料的型別:有符號數則全部新增符號位,無符號數全加 0

3    列印的時候,輸出到螢幕上時,%d 是輸出有符號數十進位制, 看CPU符號位,正數直接列印,負數符號位不變,其餘                                                                   位減1再取反

                                                        %u 是輸出無符號數十進位制    CPU符號位是0    直接列印

下面我們進入實戰演練環節:

1  

#include <stdio.h>
#include <windows.h>

int main()
{
	char a = -1;
	signed char b = -1;
	unsigned char c = -1;
	printf("a = %d b = %d c = %d\n", a, b, c);
	system("pause");
	return 0;
}

我們來分析一下: