Analysing &, && and | for this code?
-
28-06-2021 - |
Pergunta
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?
Solução
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)
.
Outras dicas
(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.
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.