Search code examples
c++bit-manipulationendianness

convert 32 bit big endian signed integer to signed little endian integer


I had some unsigned 32 bit big-endian integers that I needed to convert, and that was trivially easy once I found the right header:

#include <endian.h>
...
be32toh(some_int);

However, endian.h specifies these are for unsigned integers. For a signed integer, I'm not really sure what to do, as it doesn't look like there are header files for this sort of thing, and I'm not really familiar with bit manipulation in C++.

Edit: Since there is some confusion about the format of my integer, let me explain more. I have an integer in the form

abcdefghijklmnopqrstuvwxyz012345

where each character represents a bit. the a bit represents the sign. I know that bytes are always big endian, so in addition to moving the bytes into a different order, like

yz012345qrstwx...

I also need some way to make sure that the y bit shows the sign, not just some bit in the number. I ... have no idea how to do that.

Edit: my problem was that I was thinking that the sign bit was always first in order, when that is not the case. The sign bit is always the MSB, meaning that if you're in little-endian form, the sign bit is going to be in the middle of the bytes that make up your integer.


Solution

  • Trying to byte-reverse a signed integer doesn't sound like it's a well-defined arithmetic operation, because the most significant bit behaves as an indicator of the sign of the integer, and it wouldn't make much sense to move that elsewhere when manipulating an integer variable.

    More likely, you may have sequence of 4 bytes that represent a 32-bit signed integer, but need to be byte-reversed in order to translate between different CPU endiannesses. To do that, you can simply treat the quantities as though they were unsigned, and let be32toh() do the work for you:

    (int)be32toh((unsigned)some_int);
    

    or, slightly safer:

    (int32_t)be32toh((uint32_t)some_int);
    

    This works because the casting operations, when applied to integers of the same bit-depth, effectively leaves the in-memory representations unchanged. This ignores the significance of the sign (and any subtleties related to the twos-complement representation of signed integers) while doing the byte-reversal. I'm not sure that this behaviour is guaranteed by the C standard (a question for language lawyers, perhaps), but it's likely to be a very common behaviour. The description at www.cplusplus.com indicates that provided your system uses twos-complement representation for its signed integers (which is very common) then the signed-to-unsigned conversion in (uint32_t)some_int will do the right thing. However, the precise interpretation of the signed-to-unsigned conversion in (int32_t)be32toh(...) is, strictly, implementation dependent. So, again, I think the question of what it would mean to byte-reverse a signed integer isn't mathematically unambiguous.