淺析資料在記憶體中的儲存
一個變數所具有的兩個屬性,一是型別,二是內容。而型別決定了這個變數的在記憶體中開闢空間的大小,不同的型別對應的儲存空間不同,那麼計算機是如何儲存這些變數的呢?
首先,我們知道計算機中的符號數有三種表示方法。分別為原始碼、反碼、補碼:
- 原始碼 將資料按照二進位制的正負數形式翻譯成二進位制序列
- 反碼 原始碼的符號為不變,其餘二進位制位取反
- 補碼 反碼加一
注:對於正數,其原始碼、反碼、補碼相同
對於整形來說:資料存放在記憶體中的資料就是補碼
-
大小端概念
- 大端儲存模式:資料的低位儲存在記憶體的高地址,高位儲存在記憶體的低地址
- 小端儲存模式:資料的低位儲存在記憶體的低地址,高位儲存在記憶體的高地址
設計小程式來判斷當前機器的大小端
#include<stdio.h> #include<stdlib.h> int check_sys1() { int i=1; char * p = (char*)&i; return * p; } int check_sys2() { union { int i ; char a; }un; un.i = 1; return un.a; } int main() { int ret = check_sys2(); if (ret== 1) { printf("小端\n"); } else { printf("大端\n"); } system("pause"); return 0; }
關於資料在記憶體中的儲存問題的題目
1.
#include <stdio.h> int main()
{
char a= -1;
signed char b=-1;
unsigned char c=-1;
printf("a=%d,b=%d,c=%d",a,b,c);
return 0;
}
首先計算機儲存的是補碼,a是一個有符號的字元型資料,而且是負數,所以補碼就是 11111111,但a在輸出的時候按"%d"格式輸出,所以就需要整型提升,提升時候看什麼呢?看原生型別,也就是a定義的型別,因為a是有符號的且為負數,所以就補1,變成11 11 11 11。在輸出的時候對a進行解碼,結果就是-1,b,c照著這個思路進行就可得出結果。
2.
#include <stdio.h>
#include<stdlib.h>
int main()
{
char a = -128;
printf("%u\n", a);
system("pause");
return 0;
}
這個題和第一個不同的地方在於計算它的補碼時超過其型別(char)大小,你需要明白,當cpu將記憶體中的值讀取到cpu時,允許超過其型別大小,理解這點,分析過程和第一題一樣。
3.
#include <stdio.h>
#include<stdlib.h>
int main()
{
char a = 128;
printf("%u\n", a);
system("pause");
return 0;
}
a正數的最大值只能取到127,表明初始化超範,但這並不影響我們分析,我們可以不考慮其數值大小,直接將其當成一個普通資料,但是當發生整形提升時,有符號a在計算機中儲存為9位(0 1000 0000),但是這個時候你不能把它真正的符號位當作提升時看的符號位,char大小為8位,計算機讀取時認為它的第八位就是最高位,對於有符號數來說也就是它的符號位,第二題也存在這種問題。總結一下,對於此類問題,保持一個原則,即看它當前型別的最高位
4.
int main()
{
char a[1000];
int i;
for(i=0; i<1000; i++)
{
a[i] = -1-i;
}
printf("%d",strlen(a));
return 0;
}
這個問題的關鍵有兩點,陣列a的元素型別是char,範圍為-128到127,所以迴圈1000次肯定會造成範圍溢位;再一個就是要明白,strlen的結束標誌;這兩點明白了,這個題目分析起來也就順暢了。儲存的元素-1到-128,等到負的最大值時,下一個數是多少呢?如果前面的問題你明白了,那麼這裡顯然就是127,不解釋!接著儲存127-1。這就是陣列a中儲存的所有元素。
- 注:有符號數正數的最大值比負數的最小值絕對值差1;無符號和有符號最大值加1都等於最小值(最大值、最小值指的是這個型別的取值範圍)
5.
#include <stdio.h>
unsigned char i = 0;
int main()
{
for(i = 0;i<=255;i++)
{
printf("hello wolrd\n");
}
return 0;
}
死迴圈!
通過上面題目的分析,大家對於整型提升也有了一個清晰的認識。這類問題關鍵在於你對資料在記憶體中的儲存的理解,理解到位了,這些問題都是紙老虎:)