Search code examples
cbit-manipulationbitwise-operators

Using given bitwise operators to reproduce function


I have a question very similar to the one here Checking bits of ints to see if they share binary with the power of 2 (bitwise only) , however the question was frankly poorly worded (so i'm not sure how similar they are) and the answer was not explained much.

Trying to replicate this function:

    int testdl4(int x) {
       int i;
       for (i = 1; i < 32; i+=2)
           if ((x & (1<<i)) == 0)
              return 0;
       return 1; 
    }

Using only these bit-wise operators: !, ~, &, ^, |, +, <<, and >> (Meaning no loops or if statements either).

The answer on aforementioned link (Same question I think, but with loop starting at 0) was:

return !((x & 0x55555555) ^ 0x55555555);

And I believe the mask needs to be changed to get it to work, but I am not sure 2 what.

Could someone please solve & explain reasoning?


Solution

  • Let's start by writing what your code actually does, in English:

    If any odd numbered bit (from 1 to 31) is clear return 0; otherwise return 1.
    

    Now "any odd numbered bit (from 1 to 31)" is the binary value 10101010101010101010101010101010b, which is 0xAAAAAAAAUL. Note that this value is not possible for signed 32-bit integers, so we want to use unsigned integers that are at least 32 bits.

    If any bit is clear, then x & 0xAAAAAAAAUL won't be equal to 0xAAAAAAAAUL.

    That gives:

    int testdl4(unsigned long x) {
        if( (x & 0xAAAAAAAAUL) != 0xAAAAAAAAUL) {
            return 0;
        }
        return 1;
    }
    

    Note that this does include an if to get the same behavior as your original code (e.g. returning 1 and not returning a messed up non-zero value).

    However, the logical NOT ! will force a non-zero value to become zero and a zero value to become 1; so you can do:

    int testdl4(unsigned long x) {
        return !((x & 0xAAAAAAAAUL) ^ 0xAAAAAAAAUL);
    }