C資料儲存與提取
在c語言中,不同型別的資料在記憶體中基本上沒有差異,那麼這些定義的型別的作用是啥呢?這些定義的型別是來改變編譯器對這些資料提取時的方式,下面讓我們來看一些經典例題!!
#include<stdio.h> #include<Windows.h> int main() { unsigned int i; for (i = 9; i >= 0; i--) //i永遠為正嘛,肯定會死迴圈 { printf("%u\n", i); Sleep(1000); } return 0; }
這裡的i是一個無符號整形定義的數;
從迴圈大體來看,因為i為無符號整形,所以無論如何i的值都恆為正(先不管它為多少),所以這裡肯定是一個死迴圈;
(sleep函式是讓待會的結果暫留,便於觀察輸出的哪些數)
很輕鬆可知,在i從9到0會正常輸出 9、8、7、6、5.......2、1、0
當減為零的時候,下一個將會輸出什麼呢,我們來分析一下:
0在記憶體中為(補碼):00000000 00000000 00000000 00000000
-1在記憶體中為(補碼): 11111111 11111111 11111111 11111111
做和 : 11111111 11111111 11111111 11111111
此時輸出這個數,由於是按%u(無符號)輸出,所以編譯器直接把這個數轉成十進位制輸出(不管它的最高位)
11111111 11111111 11111111 11111111轉成十進位制為:4294967295
然後又按照這個數每次減一.......
例二 :
#include<stdio.h> #include<string.h> int main() { char a[1000]; int i; for (i = 0; i < 1000; i++) { a[i] = -1 - i; } printf("%d\n", strlen(a)); return 0; }
char型別的取值範圍為:-128~127
所以按照這樣減下去,當i等於127時,下一個就會開始超出範圍溢位
當i=255時,a[255] = -256 ; -256在記憶體中為(補碼):1 0000 0000 (這種型別的要記住,有規律) (例:-128:1000 0000)
又因為為char型別(八個位元位),所以在記憶體中儲存該資料時要發生截斷(多了一個位元位),截斷後為: 0000 0000
此處截斷了最高位(符號位)
所以a[255] = 0; strlen函式遇到0就會截止(不計入0那一個),所以答案為255;
(注意:‘\0’的ASCII值就是0)
執行結果:
例三:(註釋把原因寫得很清楚)
#include<stdio.h>
#include<math.h>
int main()
{
short num = 32767; // num的補碼: 01111111 11111111
short int a = num + 1; //a的補碼: 10000000 00000000
printf("%d\n", a); //因為按%d輸出,所以先整形提升
//整形提升後:11111111 11111111 10000000 00000000(補碼)
// 11111111 11111111 01111111 11111111(反碼)
// 10000000 00000000 10000000 00000000 (-32768)輸出結果:-32768
return 0;
}