Today I was trying to implement reading of ushort
values from a little-endian byte array. The code to retrieve a single value was pretty simple – shift the second byte by 8 to the left and add the first byte:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var result = (ushort)(data[position + 1] << 8 + data[position]); |
What could possibly go wrong?
It turned out quite a bit. The code was giving me completely wrong results. So I used BitConverter.ToUInt16
and indeed the values returned were entirely different than mine. I checked the binary notation via calculator and then it hit me. The innocent looking <<
operator has lower precedence than +
(as confirmed by the documentation). This means my code first performed:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
8 + data[position] |
And then shifted data[position + 1]
by the resulting number to the left. When I instead rewrote the code as:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var result = (ushort)((data[position + 1] << 8) + data[position]); //note the additional parentheses |
Everything was working great again.
The moral of this story is – whenever in doubt, add two keystrokes worth of parentheses. The code will be more understandable to you, other developers and especially to the computer.
PS: I ended up editing the code once more and replaced +
by logical OR, which not only shows the intention better but also leaving out the parentheses will, in this case, not have such fatal consequences.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var result = (ushort)((data[position + 1] << 8) | data[position]); |