C 語言的資料型別寬度擴充套件

2021-07-08 10:03:02 字數 2697 閱讀 8351

**編譯執行環境: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...