Search code examples
c++type-conversionbitwise-operatorssign

Would sign be lost: zeroing out the low-order bits


I have a Coord class like this:

class Coord
{
public:
    Coord(int32_t x, int32_t y, int32_t z): mVec{{x, y, z}} {}
    
    int32_t operator[](size_t i) const { assert(i < 3); return mVec[i]; }

private:
    std::array<int32_t, 3> mVec
}

Now I use my class:

Coord origin(-1, 2, -4);

uint32_t DIM = 1 << 12; // 2 ^ 12

// zero out the low-order bits
Coord originAfter = Coord(origin[0] & ~(DIM - 1),
                          origin[1] & ~(DIM - 1),
                          origin[2] & ~(DIM - 1));

Does originAfter lose the sign of origin?

UPDATE

The code is available here.


Solution

  • In hexadecimal DIM is 00001000, DIM-1 is 00000FFF, and ~(DIM-1) is FFFFF000. Then the & operation preserves all bits that are set in ~(DIM-1) and zeroes all bits that are clear in ~(DIM-1). So the lower 12 bits are zeroed and the upper 20 bits are preserved. Since the sign bit is the highest bit it is preserved.

    Technically however this is undefined behaviour when used on a negative number. In that case the result of origin[0] & ~(DIM - 1) is a large unsigned quantity which overflows when assigned to mVec[0] which is a signed quantity. Not really a problem in the real world though.