2

Suppose I have two variables of type int, a and b, and a flag F.

#define F <something>

int a = <something> ;
int b = <something> ;

What is a simple way to test that both a and b, have the flag F, or none of them has it?

To test if both of them have it, I can use something like:

if ( a & b & F )

To test if none of them has it, I can use something like:

if ( !((a & F) || (b & F)) )

And the whole test becomes:

if ( (a & b & F) &&  !((a & F) || (b & F)) )

But this looks, too long and too complicated. Is there any simpler solution?

Bite Bytes
  • 1,455
  • 8
  • 24

3 Answers3

3

The test for "none of them has it" can be

!((a | b) & F)

Merge the flags, mask and flip the logic.


The whole test can be written using xor. (Thanks to Martin James for the idea)

!((a ^ b) & F)

This means "not (exactly one of a or b has F)"

MikeCAT
  • 73,922
  • 11
  • 45
  • 70
  • `!((a | b) & F)` Is this De Morgan's laws? because I think `!((a | b) & F)` is equivalent to `!( (a&F) | (b&F) )` and not `!( (a&F) || (b&F) )` – Bite Bytes Aug 19 '17 at 13:09
  • @BiteBytes None of `!( (a&F) | (a&F) )` and `!( (a&F) || (a&F) )` is equivalent to `!((a | b) & F)`: both of the first two uses `a` twice while the last one uses `a` and `b`. – MikeCAT Aug 19 '17 at 13:11
  • @BiteBytes `(a | b) & F` is equivalent to `(a & F) | (b & F)` and isn't equivalent to `(a & F) || (b & F)`, the difference is that `|` operator does bitwise OR and `||` operator does logic OR. But adding `!` operator, which does logic NOT, to all of them, all should be equivalent. – MikeCAT Aug 19 '17 at 13:18
2

You are looking for bit equality, which can be tested by applying XOR operator ^, inverting the result, and masking.

a ^ b sets bits to 1 only where the corresponding bits of a and b are different. For corresponding bits that are the same the result bit will be set to zero.

If you invert the result, you'd get ones in positions of equal bits:

~(a ^ b)

The only thing that remains is to mask with F, and check for equality:

if ((~(a ^ b) & F) == F) {
    ... // All bits indicated by F are set to the same value in a and b
}
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
2

Maybe this one

!((a & F) ^ (b & F))
0___________
  • 60,014
  • 4
  • 34
  • 74
  • 1
    More readable but possibly one more opcode than `!((a ^ b) & F)`. Also a bit error prone as the elegant symmetry might make the reader assume that it would work for different flags as in `!((a & F1) ^ (b & F2))` which is not true. – chqrlie Aug 19 '17 at 13:21
  • Yes - it is intentional as OP is learning bitwise operations. It gives the same output despite of optimisation level. https://godbolt.org/g/SmXL9N – 0___________ Aug 19 '17 at 13:25
  • interesting how gcc unlike clang produces the same code at `-O0` and clang produces the same code at `-O2` unlike gcc that shares the code with a `jmp`. – chqrlie Aug 19 '17 at 13:32
  • 1
    @chqrlie the chosen solution does not work :) and produces when corrected the worst code – 0___________ Aug 19 '17 at 13:37
  • @chqrlie I have tested only gcc – 0___________ Aug 19 '17 at 14:12