vcsjones
vcsjones

Reputation: 141678

Bitshifting and sign

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

Answers (2)

Jean Logeart
Jean Logeart

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

user2357112
user2357112

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

Related Questions