這是一個經典的「有符號數 vs 無符號數」誤區。本文通過二進制補碼原理徹底講透。
FBB4 (16 進制)64436 (無符號 16 位整數)-1100 (有符號 16 位整數,short/int16)F B B 4
1111 1011 1011 0100 ← 16 位二進制
直接按權展開:
1×2^15 + 1×2^14 + 1×2^13 + 1×2^12 +
1×2^11 + 0×2^10 + 1×2^9 + 1×2^8 +
1×2^7 + 0×2^6 + 1×2^5 + 1×2^4 +
0×2^3 + 1×2^2 + 0×2^1 + 0×2^0
= 64436
原碼: 1111 1011 1011 0100
取反: 0000 0100 0100 1011
+1: 0000 0100 0100 1100 = 0x044C = 1100
-1100| 語言/類型 | 0xFBB4 結果 | 說明 |
|---|---|---|
C/C++ unsigned short | 64436 | 無符號 |
C/C++ short / int16_t | -1100 | 有符號補碼 |
Java short | -1100 | 固定有符號 |
Python int.from_bytes(b'\\xfb\\xb4', 'big', signed=True) | -1100 | 顯式指定 |
JavaScript new DataView(buf).getInt16(0) | -1100 | 有符號讀取 |
想要 -1100(當作有符號 16 位):
// C/C++
int16_t val = (int16_t)0xFBB4; // -1100
// Java
short val = (short)0xFBB4; // -1100
// Python
val = int.from_bytes(bytes.fromhex('FBB4'), 'big', signed=True)
想要 64436(當作無符號 16 位):
// C/C++
uint16_t val = 0xFBB4; // 64436
// Java (無無符號 short,用 int 接收)
int val = 0xFBB4 & 0xFFFF; // 64436
// Python
val = int.from_bytes(bytes.fromhex('FBB4'), 'big', signed=False)
同一組二進制位,賦予「有符號」或「無符號」語義,得到完全不同的數值。一定要明確數據類型定義,不要憑直覺轉換。網絡協議、文件格式、硬體寄存器文檔會明確註明是 signed 還是 unsigned。