**編譯執行環境:windows 64bits+vs2017+debug+win32
在程式設計或者面試過程中,關於資料型別寬度的擴充套件,可能會遇到如下問題:
char c=128;
printf("%d",c); //輸出-128
為什麼乙個正整數 128 以整型 int 輸出時變成了乙個負數?
在理解上面的問題時,我們需要先了解如下問題。
char 型所能表示的資料範圍是 -128~127。當把 128 賦值給 char 型變數時,那麼記憶體中實際儲存的是什麼呢?將以上面的**在 debug 模式下轉到反彙編,彙編**如下:
char c=128;
00b16ab0 mov byte ptr [c],80h
printf("%d",c);
00b16ab4 movsx eax,byte ptr [c]
00b16ab8 mov esi,esp
00b16aba push eax
00b16abb push 0b1ec90h
00b16ac0 call dword ptr ds:[0b2240ch]
00b16ac6 add esp,8
00b16ac9 cmp esi,esp
00b16acb call __rtc_checkesp (0b113cfh)
從彙編**可以看出,char 型變數 c 中儲存的是 128 的補碼,也是 128的原碼:10000000b。注意對於計算機來說,整型數值儲存的都是補碼,而反碼、原碼是為了方便程式設計人員理解資料的變換而提出來的。
當 char 轉換為 int 時,記憶體中的資料如何從 1 個位元組擴充套件到 4 個位元組?這個是本文的核心問題,理解了這個,就可以很好地解釋為什麼char c=128;printf("%d",c)
輸出的是 -128。
當 char 型擴充套件到 int 型時,c 標準中有如下規則:
(1)短資料型別擴充套件為長資料型別。
(a)要擴充套件的短資料型別為有符號數,進行符號擴充套件,即短資料型別的符號位填充到長資料型別的高位元組位(即比短資料型別多出的那一部分),保證擴充套件後的數值大小不變
char x=10001001b; short y=x; 則y的值應為11111111 10001001b; //例1
char x=00001001b; short y=x; 則y的值應為00000000 00001001b; //例2
(b)要擴充套件的短資料型別為無符號數,進行零擴充套件,即用零來填充長資料型別的高位元組位。
unsigned char x=10001001b; short y=x; 則y的值應為00000000 10001001b; //例1
unsigned char x=00001001b; short y=x; 則y的值應為00000000 00001001b; //例2
(2)長資料型別縮減為短資料型別。
如果長資料型別的高位元組全為 1 或全為 0,則會直接擷取低位元組賦給短資料型別;如果長資料型別的高位元組不全為 1 或不全為 0,則轉換就會發生錯誤。
(3)同一長度的資料型別中有符號數與無符號數的相互轉化。
直接將記憶體中的資料賦給要轉化的型別,數值大小則會發生變化,因為以不同型別解釋同一段記憶體資料會得到不同的數值。比如乙個位元組中存放的資料是 1111 1111b,以 unsigned char 來解釋是 255,以 char 來解釋是 -1。
根據以上規則,可以得出當 char c 是乙個有符號的字元變數,其記憶體中儲存的是 1000 0000,但當它被傳送到 printf() 函式的引數時,是將 c 按照 int 來進行寬度擴充套件後再傳給 printf()。
128 的補碼是 1000 0000b,16 進製是 0x80,當它擴充套件為 int 時,由於 int 是 4 個位元組,需要進行短資料型別擴充套件到長資料型別。由於記憶體中存放的是 10000000,以 char 型來解釋的話第一位為符號位,表示負數,進行符號擴充套件為 int 後,int 型變數中儲存的資料是:11111111 11111111 11111111 1000000,即 0xffffff80。以 int 來解釋的這四個位元組的資料,其值就是 -128,以 unsigned int 來解釋的話,就是232−
1−
127=
4294967168
2^-1-127=4294967168
232−1−
127=
4294
9671
68。根據以上分析,我們可以清楚準確地推斷出下面的輸出。
unsigned char uc=128;
char c=128;
printf("%d\n",uc); //128
printf("%d\n",c); //-128
printf("%u\n",uc); //128
printf("%u\n",c); //4294967168
printf("%08x\n",uc); //0x00000080
printf("%x\n",c); //0xffffff80
應該不會為這些輸出結果而感到驚訝和困惑了吧!
[1] 型別擴充套件
[2] char c=128
dede擴充套件資料型別 資料型別擴充套件
資料型別擴充套件 整數擴充套件 整數的進製有二進位制 0b 八進位制 0 十進位制,十六進製制 0x 例 int num1 10 int num2 0b10 int num3 010 int num4 0x10 system.out.println num1 system.out.println n...
C ,資料型別擴充套件 z
macd的公式 diff ema close,short ema close,long dea ema diff,m macd 2 diff dea colorstick 它的變數是可以直接進行加減 除的,但是我們要知道,它裡面的close這個東西實際上也是乙個陣列型別的。同過總結分析我們可以知道。...
資料型別擴充套件
進製 二進位制0b 十進位制 八進位制0 十六進製制0x int i1 0 int i2 0b10 二進位制 int i3 010 八進位制 int i4 0x10 十六進製制 system.out.println i1 0 system.out.println i2 2 system.out.pr...