整形資料在記憶體中的儲存
整型資料在記憶體中的儲存,是一個值得細細體會的問題,千萬不要把它忽視了!!!下面我們來詳細談一談:
什麼是整形?
整形有: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;
}
我們來分析一下: