Zero or sign extend

submited by
Style Pass
2024-10-24 01:00:03

A while back I had to deal with a bit-packed format that contained a list of integer values encoded in one of a pre-defined sets of bit widths, where both the allowed bit widths and the signed-ness were denoted in a header elsewhere. These values never got particularly long (the largest bit width I needed to support was around 14 bits I think?) but having a mixture of different bit widths and signedness-es (is that a word?) was annoying to deal with, particularly the latter. Signed values were stored in the usual two’s complement format.

In particular, sign-extending narrow types is surprisingly awkward. Most people’s go-to solution seems to be shifting the value up in a wider integer type to move the narrow value’s sign bit into the containing types sign bit, then use an arithmetic shift to repeat the sign bit on the way down. That’s a mouthful. I’m talking about code like this:

In C/C++, this explicitly relies on shifting something into the sign bit, which depending on the exact flavor of language standard you’re using is either not allowed or at best fairly recently (voted into C++20) legal. It also explicitly needs to work with a fixed-size integer representation to know what to shift by. That’s not a problem, just not aesthetically pleasing.

Leave a Comment