首頁 > 軟體

C語言資料的儲存超詳細講解中篇練習

2022-04-14 10:02:11

前言

本文繼續學習資料在記憶體中儲存的相關知識點。

  • 資料儲存
  • 整型提升

資料的儲存的知識點練習

通過幾個練習來深入學習資料在記憶體中儲存的知識點,先複習前面學過的整形提升的知識點:C語言操作符超詳細講解下篇

整形提升是按照變數的資料型別的符號來提升的

負數的整形提升,最高位補充符號位,即1,例如

char a=-1;
11111111 截斷後的二補數
11111111111111111111111111111111 整形提升後

正數的整形提升,最高位補充符號位,即0,例如:

char a=1;
00000001 截斷後的二補數
00000000000000000000000000000001 整形提升後

無符號型別的整形提升,最高位直接補充符號位,即0,例如:

unsigned char c = -1;
11111111 截斷後的二補數
00000000000000000000000011111111  整形提升後

練習 1

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

查德一看,以為結果是 -1,-1,-1,下面具體分析:

    1、char a = -1;
第一步:-1是整數,在記憶體的儲存形式
    10000000000000000000000000000001  -1原碼
    11111111111111111111111111111110  -1反碼
    11111111111111111111111111111111  -1二補數
第二步:賦值給變數a,截斷二補數低位元組的資料
    11111111
第三步:以%d的形式列印,先要整形提升,
       因為變數a是有符號,且是負數,所以高位補1
    11111111111111111111111111111111  二補數
    11111111111111111111111111111110  反碼
    10000000000000000000000000000001  原碼
第四步:最終列印是的原碼,數值是十進位制 -1
    
    2、signed char b = -1;
    過程同有符號變數a的分析過程
    
    3、unsigned char c = -1;
第一步:-1在記憶體的儲存形式
    10000000000000000000000000000001  -1原碼
    11111111111111111111111111111110  -1反碼
    11111111111111111111111111111111  -1二補數
第二步:賦值給變數c,截斷二補數低位元組的資料
    11111111
第三步:以%d的形式列印,先要整形提升,
    因為變數c是無符號的,最高位1為資料位,
    不是符號位,所以高位直接補0
    00000000000000000000000011111111  二補數
第四步:因為正數三碼相同
    最終列印的是原碼,數值是十進位制255

結果見下圖:

練習 2

int main()
{
	char a = -128;
	printf("%un", a);
	return 0;
}

查德一看,以為結果是 -128,下面具體分析:

    char型別 有符號型別資料範圍 -128-127
    char a = -128;
第一步:-128在記憶體的儲存形式
    10000000000000000000000010000000 原碼
    11111111111111111111111101111111 反碼
    11111111111111111111111110000000 二補數
第二步:賦值給char 變數a,發生截斷,取低位元組資料
    10000000 - a
第三步:列印%u,首先進行整形提升
    因為變數a是有符號,且是負數,所以高位補充符號位,即補1
    11111111111111111111111110000000 二補數 負數
第四步:%u,認為是無符號資料,即正數。最高位1為資料位
    11111111111111111111111110000000 二補數 正數
第五步:因為正數三碼相同
    最終列印的是原碼,數值是十進位制4,294,967,168

結果見下圖:

練習 3

int main()
{
	char a = 128;
	printf("%un", a);
	return 0;
}

查德一看,以為結果是 128,下面具體分析:

第一步:整形128在記憶體的儲存形式
    00000000000000000000000010000000 原碼=反碼=二補數
第二步:賦值給char型別 a,發生截斷,取低位元組資料
    10000000 - a
第三步:按照%u列印,先對a進行整型提升,
    因為變數a是有符號,且是負數,所以高位補充符號位,即補1
    11111111111111111111111110000000 二補數 負數
第四步:%u,認為是無符號資料,即正數。最高位1為資料位
    11111111111111111111111110000000 二補數 正數
第五步:因為正數三碼相同
    最終列印的是原碼,數值是十進位制4,294,967,168

結果見下圖:

練習 4

int main()
{
	int i = -20;
	unsigned int j = 10;
	printf("%dn", i + j);
	return 0;
}

查德一看,以為結果是 -10,下面具體分析:

第一步:整形 -20 在記憶體的儲存形式
    10000000000000000000000000010100 原碼
    11111111111111111111111111101011 反碼
    11111111111111111111111111101100 二補數
第二步:整形 10 在記憶體的儲存形式
    00000000000000000000000000001010 原碼
    00000000000000000000000000001010 反碼
    00000000000000000000000000001010 二補數
第三步:i + j    二補數相加
    11111111111111111111111111101100 -20的二補數
    00000000000000000000000000001010 10的二補數
    11111111111111111111111111110110 相加後的二補數
第四步:最終列印的是原碼,數值是十進位制 -10
    11111111111111111111111111110101 反碼
    10000000000000000000000000001010 原碼    

結果見下圖:

練習 5

int main()
{
	unsigned int i = 0;
	for ( i = 9	; i >=0; i--)
	{
		printf("%un", i);
	}
	return 0;
}

查德一看,以為結果是9 到0,共10個數,下面具體分析:

  1、i從9到0時,
    是正常的輸出9到0
  2、i=-1時
第一步:-1是整數,在記憶體的儲存形式
    10000000000000000000000000000001  -1原碼
    11111111111111111111111111111110  -1反碼
    11111111111111111111111111111111  -1二補數
第二步:-1賦值給無符號型別時,認為最高1為資料位
    11111111111111111111111111111111  變成的正數的二補數了
    數值大於0,又進入迴圈了,所以是死迴圈

結果見下圖:

練習 6

int main()
{
	char a[1000];
	int i;
	for (i = 0; i < 1000; i++)
	{
		a[i] = -1 - i;
	}
	printf("%dn", strlen(a));//字串長度,字元''之前的字元個數
	printf("%dn", sizeof(a));//字串中字元的個數
	return 0;
	
}

查德一看,以為結果是1000、1000,下面具體分析:

    char型別 有符號型別資料範圍 -128-127
  1、i從0到127時,
    是正常的輸出-1 -2 -3 ....-128
  2、i=128時
  a[128]=-129
第一步:-129是整數,在記憶體的儲存形式
    10000000000000000000000010000001 原碼
    11111111111111111111111101111110 反碼
    11111111111111111111111101111111 二補數
第二步:-129 賦值給char型別a[128]時,發生截斷,取低位元組資料
    01111111 - a[128]=127

strlen求得字串長度,是字元 ‘’ 之前的字元個數,而第256個元素a[256]=0時,ASCII碼值就是0,也就是字元 ‘’ 的ASCII碼值,於是認為字串到此結束了,strlen(a)=255。

所以陣列的元素規律是:

  • 從-1到-128
  • 然後輸出127到0
  • 又從-1到-128
  • 然後輸出127到0
  • 這是一個迴圈,是一個圓

sizeof(a)求取字串中字元的個數,sizeof(a)=1000:

陣列中一共有1000個字元,第256個元素為0,ASCII碼與字元’’, 一樣,即字串到此結束,strlen(a)=255。 ,從256到999都是有元素存在的,sizeof(a)=1000。下面是輸出結果。

練習 7

unsigned char i = 0;//無符號型別的資料範圍是:0-255
int main()
{
	for ( i = 0; i <=255; i++)
	{
		printf("hello worldn");
	}
	return 0;
}

查德一看,以為結果是列印256行 hello world,下面具體分析:

1、i從0到255時
    正常列印 hello world
2、當i=256時
第一步:i=256,在記憶體中的儲存形式
    00000000000000000000000100000000 二補數
    賦值給無符號char i,發生截斷,取低位元組資料
    00000000 - i 此時i又滿足迴圈條件了,又陷入死迴圈了

結果見下圖所示:

總結

通過7個練習來鞏固資料儲存的知識點,尤其是整型提升的內容,要注意掌握。

下一篇更新浮點型在記憶體中的儲存的相關知識點。

到此這篇關於C語言資料的儲存超詳細講解中篇練習的文章就介紹到這了,更多相關C語言 資料的儲存內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com