1. 程式人生 > >C語言有符號數截斷補位問題

C語言有符號數截斷補位問題

在程式設計師面試寶典中看到這樣一道題,下面程式的輸出結果是什麼?

    1 	#include <stdio.h>
    2 	
    3 	int main(int argc, char const *argv[])
    4 	{
    5 	  unsigned int a = 0xfffffff7;
    6 	  unsigned char i = (unsigned char)a;
    7 	
    8 	  char *b = (char *)&a;
    9 	
   10 	  printf("%08x,%08x\n", i, *b);
   11 	  return 0;
   12 	}

分析:在X86系列的機器中,資料的儲存是“小端儲存”,小端儲存的意思是,對於一個跨多位元組的資料,其低位存放在低地址單元,其高位存放在高地址單元。比如一個int型的資料0x12345678,假如存放在0x00000000,0x00000001,0x00000002,0x00000003這四個記憶體單元中,那麼0x00000000中存放的是低位的0x78,而0x00000003中存放的是高位的0x12,依此類推。

    分析第二個為什麼輸出fffffff7. &a可以認為是個指向unsigned int型別資料的指標,(char *)&a把&a強制轉換成char *型別的指標,並且這個時候發生了截斷!截斷後,指標b只指向0xf7這個資料。(為什麼 b指向最低位的0xf7而不是最高位的oxff?想想上面剛剛講過的小端儲存,低地址單元存放低位資料),又由於指標b是char*型,屬於有符號數,所以有符號數0xf7在printf()的作用下輸出fffffff7.

答案是: 000000f7, fffffff7

下面是我的理解:

     第一個結果沒有疑問,unsigned char型別的i只能取一個位元組,又因為是小端儲存,所以i發生截斷結果為0xf7,高位就補零。

第二個結果我剛開始覺得結果是跟第一個結果是一樣的,都是高位補零。

     後來發現我錯了,沒有考慮到b是char *型的,屬於有符號數,0xf7最高位為1,應該是負數,負數要顯示出來就要以補碼的形式輸出,所以高位不是補0是補1.如果我把a的值改為0xAAAAAA07,結果就都是00000007.