Java 無無符號基本類型,所有整數均為帶號。當從網路(大端序)讀取 C/C++ 發送的無符號 byte、short、int 時,必須在 Java 端以更寬的帶號類型(short、int、long)接收,並透過位元運算還原無符號數值。
0xFF & b 取低 8 位,轉為 short 即得 0~255。| 低位,得 0~65535,存入 int(Java char 亦為 16 位無符號)。| 合成,最後 & 0xFFFFFFFFL 強制視為 32 位無符號,存入 long。byte[] buf = getNetData(); // 假設已讀取網路資料
int index = 0;
// 1 byte → unsigned byte (0~255) → Java short
int firstByte = 0xFF & buf[index++];
short anUnsignedByte = (short) firstByte;
// 2 bytes → unsigned short (0~65535) → Java char
firstByte = 0xFF & buf[index];
int secondByte = 0xFF & buf[index + 1];
index += 2;
char anUnsignedShort = (char) (firstByte << 8 | secondByte);
// 4 bytes → unsigned int (0~4294967295) → Java long
firstByte = 0xFF & buf[index];
secondByte = 0xFF & buf[index + 1];
int thirdByte = 0xFF & buf[index + 2];
int fourthByte = 0xFF & buf[index + 3];
index += 4;
long anUnsignedInt = ((long) (firstByte << 24
| secondByte << 16
| thirdByte << 8
| fourthByte)) & 0xFFFFFFFFL;
0xFF & buf[i] 的必要性Java byte 為帶號,負值擴展為 int 時會符號擴展(高 24 位變 1)。& 0xFF 強制清零高位,只保留原始 8 位元模式,得到 0~255 的 int 值。
firstByte << 8 會先將 firstByte 提升為 int 再移位,結果仍為 int。四位元組合成時,最外層轉 (long) 確保 32 位不溢位,最終 & 0xFFFFFFFFL 消除符號位影響。
程式碼假設網路資料為 Big-Endian(高位在前),符合 RFC 1700 網路位元組序標準。若傳送端為小端序,需反轉索引順序。
public final class UnsignedBytes {
private UnsignedBytes() {}
public static int toUnsignedByte(byte b) {
return b & 0xFF;
}
public static int toUnsignedShort(byte[] buf, int offset) {
return ((buf[offset] & 0xFF) << 8) | (buf[offset + 1] & 0xFF);
}
public static long toUnsignedInt(byte[] buf, int offset) {
return (((long) buf[offset] & 0xFF) << 24)
| (((long) buf[offset + 1] & 0xFF) << 16)
| (((long) buf[offset + 2] & 0xFF) << 8)
| ((long) buf[offset + 3] & 0xFF);
}
// 便利方法:直接回傳 Java 對應寬類型
public static short asShort(byte b) { return (short) toUnsignedByte(b); }
public static char asChar(byte[] buf, int offset) { return (char) toUnsignedShort(buf, offset); }
public static long asLong(byte[] buf, int offset) { return toUnsignedInt(buf, offset); }
}
ByteBuffer:ByteBuffer.wrap(buf).order(ByteOrder.BIG_ENDIAN).getShort() 等原生方法,JIT 會優化為內部指令。offset 索引。Unsafe 或 VarHandle (Java 9+) 直接存取記憶體。| C 傳送值 | 位元組序列 | Java 解析結果 |
|---|---|---|
| uint8_t 200 | C8 | short 200 |
| uint16_t 50000 | C3 50 | char 50000 |
| uint32_t 3000000000 | B2 D0 5E 00 | long 3000000000 |
IEEE 754 浮點數位元模式可直接用 Float.intBitsToFloat/Double.longBitsToDouble 轉換。結構體序列化建議採用 Protocol Buffers、FlatBuffers 或自訂 TLV 協議,避免手工位元操作維護成本過高。
跨語言無符號整數傳輸的核心在於:位元遮罩消除符號擴展 + 移位組合還原數值 + 寬類型承載結果。掌握此模式,即可在 Java、C#、Go、Python 等無/有無符號類型語言間安全互通。