[C]有符號數和無符號數

weixin_34119545發表於2019-01-12



1. 有符號數和無符號數:
    C支援所有整形資料型別的有符號數和無符號數運算。儘管C標準並沒有指定某種有符號數的表示,但是幾乎所有的機器都使用二進位制補碼。通常,大多數數字預設都使有符號的,C也允許無符號數和有符號數之間的轉換,轉換原則是基本的位表示保持不變。因此在一臺二進位制補碼機器上,當從無符號數轉換為有符號數時,效果就是應用U2Tw,而從有符號轉換為無符號數時,就是應用函式T2Uw,其中w表示資料型別的位數。
T2Uw(x) = (x<0)?(x+2w) :x;
U2Rw(x) = (x<2w-1)?x:(x-2w);

    當執行一個運算時,如果它的一個運算數是有符號的而另一個是無符號的,那麼C會隱含地將有符號引數強制轉換為無符號數,並假設這兩個數都是非負的,來執行這個運算。e.g.(show_*函式參考《應考慮位元組順序(大小端問題)的幾種情況 ):

void TestU2T()
...{
  printf(
-2147483647-1==2147483648U?"1 ":"0 ");
   show_unsignedInt(
2147483648U);
   show_int(
-2147483647-1);
}

 

 

2. 擴充套件數字的位表示:
    當將一個較小的資料型別轉換到一個較大的資料型別時,需要擴充套件一個數字的位表示。要將一個無符號數轉換為一個更大的資料型別,我們只要簡單地在表示的開頭新增0,這種擴充套件稱為零擴充套件(Zero Extension);要將一個二進位制補碼數字轉換為一個更大的資料型別,擴充套件時需要填充最高有效位的值,這種擴充套件稱為符號擴充套件(Zero Extension)。e.g.:

void TestExtension()
...{
   
short sx = -12345;
   unsigned 
short usx = sx;
   
int x = sx;
   unsigned ux 
= usx;
   
   printf(
"sx=%d ",sx);
   show_short(sx);
   printf(
"usx=%d ",usx);
   show_unsignedShort(usx);
   printf(
"x=%d ",x);
   show_int(x);
   printf(
"ux=%d ",ux);
   show_unsignedInt(ux);
}

執行結果和結果分析:
sx=-12345       cfc7
usx=53191       cfc7
x=-12345    ffffcfc7(符號擴充套件,算術右移)
ux=53191    0000cfc7(零擴充套件,邏輯右移)

   另外:從一個資料大小到另一個資料大小,以及無符號和有符號數字之間的轉換的相對順序能夠影響一個程式的行為。e.g.(short sx=-12345): (unsigned)(int)sx != (unsigned)(unsigned short)sx

 

 

3. 截斷數字的位表示:
    當將一個較小的資料型別轉換到一個較大的資料型別時,需要截斷該數字的高N位。 

 

相關文章