1

I want to illustrate the difference with this code

for(i = 32; i > 0; i--)
 {
   if(a&1 != 0) //bit mask
     total += b;
   a = a >> 1;
   b = b << 1; 
 }

In the code & is used to "mask" a bit and the result would have been completely different if && had been used instead. In that case the expression 1 had been interpreted as a truth value (TRUE) instead of a one-bit position that is used to keep one of the bits. Correct? But what would instead happen if I did like this:

for(i = 32; i > 0; i--)
 {
   if(a|1 != 0) //bit mask
     total += b;
   a = a >> 1;
   b = b << 1; 
 }

In the first case the 1 is used to keep only the LSB (least significant bit) i.e. rightmost bit and nothing else. What would |do in its place? What would be the difference if I did this change?

Niklas Rosencrantz
  • 25,640
  • 75
  • 229
  • 424

3 Answers3

4
a&1 != 0

should be

(a&1) != 0

!= has higher precedence than &. Otherwise a&1 != 0 is read as a & (1 != 0).

Same for (a|1 != 0).

ouah
  • 142,963
  • 15
  • 272
  • 331
  • 1
    That's very interesting since these are taken from course notes in computer engineering where the code should be correct. Thank you for the answer. – Niklas Rosencrantz Aug 27 '12 at 15:43
  • @NickRosencrantz This is a very common mistake. This precedence is counter-intuitive because it is an historical bad design choice made by D. Ritchie. See here for more info: http://www.lysator.liu.se/c/dmr-on-or.html – ouah Aug 27 '12 at 15:47
1
(a | 1 ) != 0

Is true always. It has the effect of returning a but with the lowest bit set which is clearly not 0 (at least not in any C implementation I have ever seen). Similarly

(a || 1)

is always true, since 1 is true in C and anything or true is true.

JeremyP
  • 84,577
  • 15
  • 123
  • 161
1

In this very instance, your omission of braces around a&1 does not change the meaning of the program.

Since != has precedence, it will evaluate 1 != 0 which is 1 and since !=0 is an utterly redundant statement, it doesn't matter whether you say if (a OP (1 != 0)) or if ((a OP 1) != 0).

Now, we can look at your second statement and interpret it as you intended: (a | 1) != 0. The only value where all bits are zero is 0 which is on the right of the comparison but on the left side you always have a value with at least one bit set (the rightmost). Thus these will in fact never be equal, thus (a | 1) != 0 is the same as 1.

So, the difference is that (a & 1) actually checks if a is odd and increments total only then, while (a | 1) increments total in each iteration as the condition is a tautology.

bitmask
  • 32,434
  • 14
  • 99
  • 159