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

淺析資料在記憶體中的儲存

一個變數所具有的兩個屬性,一是型別,二是內容。而型別決定了這個變數的在記憶體中開闢空間的大小,不同的型別對應的儲存空間不同,那麼計算機是如何儲存這些變數的呢?

首先,我們知道計算機中的符號數有三種表示方法。分別為原始碼、反碼、補碼:

  • 原始碼      將資料按照二進位制的正負數形式翻譯成二進位制序列
  • 反碼      原始碼的符號為不變,其餘二進位制位取反
  • 補碼      反碼加一

注:對於正數,其原始碼、反碼、補碼相同

對於整形來說:資料存放在記憶體中的資料就是補碼

  • 大小端概念

  • 大端儲存模式:資料的低位儲存在記憶體的高地址,高位儲存在記憶體的低地址
  • 小端儲存模式:資料的低位儲存在記憶體的低地址,高位儲存在記憶體的高地址

設計小程式來判斷當前機器的大小端

#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;
 }

死迴圈!

通過上面題目的分析,大家對於整型提升也有了一個清晰的認識。這類問題關鍵在於你對資料在記憶體中的儲存的理解,理解到位了,這些問題都是紙老虎:)