Reputation: 141678
Let me start with the problem:
def word(byte1 : Byte, byte2 : Byte, byte3 : Byte, byte4: Byte) : Int = {
((byte4 << 0)) | ((byte3 << 8)) | ((byte2 << 16)) | ((byte1 << 24))
}
The goal here is pretty simple. Given 4 bytes, pack them in to an Int
.
The code above does not work because it appears the shift operator tries to preserve the sign. For example, this:
word(0xFA.toByte, 0xFB.toByte, 0xFC.toByte, 0xFD.toByte).formatted("%02X")
Produces FFFFFFFD
when I would have expected FAFBFCFD
.
Making the problem smaller:
0xFE.toByte << 8
Produces -2 in two's complement, not 0xFE00.
How can I do a shift without the sign issues?
Upvotes: 3
Views: 95
Reputation: 53839
Your suspicion is correct and @user2357112 answers your question.
Now, you can use ByteBuffer
as a clean alternate:
def word(byte1 : Byte, byte2 : Byte, byte3 : Byte, byte4: Byte) : Int =
ByteBuffer.wrap(Array(byte1, byte2, byte3, byte4)).getInt
Upvotes: 4
Reputation: 281584
AND the bytes with 0xFF
to undo the effects of sign extension before the shift:
((byte4 & 0xFF) << 0) | ((byte3 & 0xFF) << 8) | ...
Upvotes: 4