unsignedbitmask

Using bit masking to set 0 to 1 and everything else to 0


How could I use bit masking to make all the bits in a number 1 if they were all 0, and all 0 if they were not?

Using an unsigned variable:

So, if I have 0000-0000, I would like that to become 1111-1111. If I have 0101-0110 (or 0000-0001, or 1111-1111, etc), I would like that to become 0000-0000.

Is this possible to do without using any conditional?


Solution

  • Sure, it's possible:

    int y = 0xff;
    y = ~(y & 1 | y>>1 & 1 | y>>2 & 1 | ...) - 1
    

    But unless this is an academic exercise, you really shouldn't. If you're concerned about performance, y = y != 0 is almost certainly faster.

    Explanation:

    y & 1 takes the first bit of the number. y >> k shifts the number right by k bits, allowing us to get that bit by y >> k & 1. We simply | them together, which results in one if any bit is set or zero if not. Subtracting 1 gives us 0 if any bit was set, and -1 if not. The binary representation of -1 is 1111...

    Shift:

    1010 - y
    1010 - y >> 0
     101 - y >> 1
      10 - y >> 2
       1 - y >> 3
    

    Take the first bit:

       0 - y >> 0 & 1
       1 - y >> 1 & 1
       0 - y >> 3 & 1
       1 - y >> 4 & 1
    

    Or them:

       1 - 0 | 1 | 0 | 1
    

    Negate:

    0000 - 1-1