Are these two lines of code equivalent?
P1->OUT &= ~(uint8_t)(1<<1);
P1->OUT &= (uint8_t)(~(1<<1));
Are these two lines of code equivalent?
P1->OUT &= ~(uint8_t)(1<<1);
P1->OUT &= (uint8_t)(~(1<<1));
It depends on the type of P1->OUT, and the system. The result of 1 << 1 is of type int.
I am considering the general case of int n; instead of 1 << 1
In
P1->OUT &= ~(uint8_t)(n);
the operand will be widened to int again before the ~ (the integer promotion), and the ~ would be applied to an int. The result will have all the high-order bits 8...k set. If P1->OUT is 8 bits wide it is OK, but if it has more bits then the result is not what you'd expect.
This one is even worse:
P1->OUT &= (uint8_t)(~(n));
The ~ operand will be applied again to an int and that would be converted to uint8_t. now if ~n is actually negative (has its sign bit set) - and in case of ~(1 << 1) it would be negative - it will be fine in two's-complement implementations but totally incorrect in 1's-complement and sign-and-magnitude implementations, because the bit representations would not be the same.
The proper way to do bit twiddling is always use unsigned int or a wider two's complement number:
P1->OUT &= ~(1U << n);
or
P1->OUT &= (~(1U << n)) & 0xFF;
to avoid the arithmetic conversions and integer promotions ever producing signed numbers.
TL;DR — No! (They are not always the same, and the result depends on the type of P1->OUT.)
I'm assuming the normal case of 2's-complement arithmetic. If you suffer from sign-magnitude or 1's-complement arithmetic, you have to think quite a lot harder, but the conclusion is probably the same (not always the same).
Case 1:
(1<<1) is an int value (0x02).(uint8_t)(1<<1) converts to uint8_t, but the value is still 0x02.~(uint8_t)(1<<1) converts the uint8_t value to int again (usual arithmetic conversions) and applies the bit-wise inversion operator ~ to the result.Assuming a 32-bit int type, you get 0xFFFFFFFD to & with P1->OUT:
P1->OUT &= 0xFFFFFFFD;
Case 2:
(1<<1) is an int value (0x02).~(1<<1) is an int value — assuming 32-bit int, the value is 0xFFFFFFFD.(uint8_t)~(1<<1) casts to uint8_t, zeroing the bits in the more significant bytes.Assuming a 32-bit int type, you get 0x000000FD to & with P1->OUT:
P1->OUT &= 0x000000FD;
So, the value combined with P1->OUT is different, but the effect depends also on the (unspecified) type of P1->OUT. If it is uint8_t, then there's no difference; if it is uint64_t, there is potentially a massive difference, but it also depends on the value in P1->OUT before the compound assignment is executed.