sss
sss

Reputation: 45

What does this particular IF statement in C actually do (that also works)?

I came across some sample code which works perfectly for my application, but I am not sure what is actually going on in the IF statement.

unsigned int steps;
uint16_t selected_steps; 

for (int j = 16; j>=0; j--)
{
    if (((selected_steps^(1 << step_number))>>j) & 0x1) {
          some code...
      } else {
          other code...
      }

I know the purpose of the code, it is to check if the bit at selected_steps[j] XOR step_number is 1 or 0. Selected_steps[j] is either 0 or 1. Step number takes values between 0-15.

But I don't understand what is actually done by doing

(1 << step_number)

and then what is done by doing

selected_steps^(1 << step_number)) >> j

I suppose that the above statement outputs a 1 or 0 since it checks against 0x1?

Upvotes: 0

Views: 80

Answers (2)

Clifford
Clifford

Reputation: 93476

Break it down into steps.

uint16_t mask = 1 << step_number ; // A bit mask with single 
                                   // bit `step_number` set.

uint16_t xor_step = selected_steps ^ mask ; // Toggle bit `step_number`.

uint16_t bit_j = (xor_step >> j)  & 0x1 ;   // Get the single bit `j`

if( bit_j  ) ... // If bit j is not zero.

So for example when:

selected_steps == 0x5AA5 (binary:0101101010100101) 
j == 5
step_number == 10

then:

mask = 1 << 10 (Binary: 0000001000000000)

selected_steps: 0101101010100101
          mask: 0000001000000000
         -----------------------
           XOR: 0101100010100101 == xor_step
                      ^
                      |_ Toggled bit

                         ,- Bit 5 (j)
                         V      
     xor_step: 0101100010100101
shift right 5: >>>>>01011000101
                              ^
                              |_ Bit 5 moved to LSB

               0000001011000101         
        AND 1: 0000000000000001 == bit j

So you end up with bit j of selected_steps after bit step_number has been toggled. If j != step_number then the toggling has no effect on the result.

How that achieves the purpose of your application is not possible to tell given the aggressive eliding of your code. Presumably in reality selected_steps and step_number are not loop-invariant (and steps not unused, and selected_steps actually initialised for that matter)?

Upvotes: 1

Eric Postpischil
Eric Postpischil

Reputation: 222486

Consider what happens if step_number differs from j. Then: ((selected_steps^(1 << step_number))>>j) & 0x1 does this:

  • The XOR with 1 << step_number changes some bit of selected_steps other than bit j. But, as we will see, we do not care about this.
  • Then >>j moves bit j to position 0.
  • Then & 0x1 isolates that bit.
  • The result is true iff bit j in selected_steps is true.

On the other hand, if step_number equals j, then the XOR changes bit j, and the result is true iff bit j in selected_steps is false.

So the expression is equivalent to (step_number == j) != (selected_steps >> j & 1).

Upvotes: 4

Related Questions