一、二進制補碼
在計算機系統中,數值一律用補碼來表示和存儲,使用補碼,可以將符號位和數值域統一處理;同時,加法和減法也可以統一處理。
正整數的補碼和源碼相同;
0的補碼是0;
負數的補碼是符號位不變,原碼的各位取反,再加1。
1 1000 0000 1111 1111 …… 1000 0001 0000 0000 0000 0001 …… 0111 1111 -2^n -2^n-1 …… -1 0 1 …… 2^n-1 1 0111 1111+1 1000 0000+1 …… 1111 1110+1 0000 0000 0000 0001 …… 0111 1111 1 1000 0000 1000 0001 1111 1111
負數補碼表示的范圍比原碼稍寬,對於整數,范圍是:-2^n~2^n-1
以下參考:https://blog.csdn.net/qq_29545231/article/details/78622927
在32位機中定義signed short a =0xeeee;
執行printf(“%d\n”,a),printf(“0x%x\n”,a)的結果分別是什么呢?
signed short a = 0xeeee; printf("%d\n",a); printf("0x%x\n",a);
結果:
-4370 0xffffeeee
0xeeee=1110 1110 1110 1110,是有符號short型,在計算機中,負數是以補碼形式存儲的,即:符號位不變,原碼各位取反加一。
現在已知負數在計算機中的存儲的數值(所以變量初始化時用的十六進制,就直接初始化成補碼了啊),再求這個值,順序就反了,先減一再按位取反:
1110 1110 1110 1110——減1——>1110 1110 1110 1101——按位取反——>1001 0001 0001 0010,最高位1是負數,001 0001 0001 0010是4370,所以值為4370。
但是在32位機中,使用printf函數進行輸出時都會進行類型隱式轉換,轉換為4字節的類型。
有符號類型(signed char)無論向有符號類型(int)還是無符號類型(unsigned int)轉換,都會按照有符號數的轉換規則(高位補符號位)。
無符號類型(unsigned char)無論向有符號類型(int)還是無符號類型(unsigned int)轉換,都會按照無符號數的轉換規則(高位補0)。
0xeeee是有符號位,高位補1,所以打印輸出為:0xffffeeee
若0xeeee非要輸出16位,可把變量強制轉化:
printf("0x%x\n",(unsigned short)a);
輸出結果:
0xeeee
上面的強制轉化只為了打印顯示,實際值大小變了。
所以對於二進制補碼形式的編碼,正負過渡不方便時,可以直接用十進制數來過渡。
二、偏移二進制碼
把補碼的符號位取反就是偏移二進制碼。
如16位的數,0x0000是-32768,0x8000是0,0xFFFF是32767,偏移二進制碼用十六進制時正負過渡比較方便