Ian Collins:
Suprisingly, the compiler produced more efficient code for the latter,
presumably because it recognises the pattern of " x &= ~y" for
clearing a single bit.
Odd, is x an unsigned 8 bit type?
Yes, it is.
If so, the two expressions should
generate identical code.
If I do:
y &= ~0x08u;
then I get the following assembler:
BCF y, 0x3 /* Clear the 4th bit of y */
If I do:
y &= 0x7Fu;
then I get the following assembler:
MOVLW 0x7f /* Load the accumulator with 0x7f */
ANDWF y, F /* AND y with the accumulator
and store the result in y */
The former is one instruction, while the latter is two, and as all
instructions take the same amount of CPU cycles, the latter version is
exactly twice as slow.
Not only that, but things get even worse if you do the following:
if (whatever) y &= ~0x08u;
versus:
if (whatever) y &= 0x7Fu;
On the PIC micrcontroller, there's an instruction that does the
following: "Check whether the last arithmetic operation resulted in
zero, and if so, skip the next instruction". Since the former version
is comprised of a single instruction, this single instruction can be
skipped by the conditional. However, in the case of the latter form
which consists of two instructions, there has to be an interleaving
goto statement. Result: WAY slower.