Operators and bit operations
&& and || are logical and give 0 or 1; &, |, ^ and ~ work bit by bit. Set a bit with |= 1u << n, clear it with &= ~(1u << n) and toggle it with ^=. Use unsigned constants: shifting into a signed sign bit is undefined.
Logical or bitwise?
The logical operators &&, || and ! treat a whole value as true (non-zero) or false (zero), give an int 0 or 1, and stop early: in a && b, b is not evaluated when a is false. The bitwise operators &, |, ^ and ~ work on every bit separately and always evaluate both sides. So 2 && 1 is 1, but 2 & 1 is 0, because the two values share no set bit.
Shifts and masks
1u << n is a mask with only bit n set. With it, four idioms cover most register code: reg |= 1u << n sets the bit, reg &= ~(1u << n) clears it, reg ^= 1u << n toggles it, and (reg >> n) & 1u reads it. Write 1u, not 1: with a 32-bit int, 1 << 31 shifts into the sign bit, which is undefined, and right-shifting a negative value is implementation-defined.
#include <stdint.h>#include <stdio.h>static void show(const char *label, uint8_t v) { printf("%-9s0x%02X ", label, (unsigned)v); for (int i = 7; i >= 0; i--) { putchar(((v >> i) & 1u) ? '1' : '0'); } putchar('\n');}int main(void) { uint8_t reg = 0xA5; /* 1010 0101 */ show("start", reg); reg |= (uint8_t)(1u << 1); /* set bit 1 */ show("set 1", reg); reg &= (uint8_t)~(1u << 5); /* clear bit 5 */ show("clear 5", reg); reg ^= (uint8_t)(1u << 0); /* toggle bit 0 */ show("toggle 0", reg); printf("bit 7 is %u\n", (unsigned)((reg >> 7) & 1u)); printf("2 && 1 = %d, 2 & 1 = %d\n", 2 && 1, 2 & 1); return 0;}
start 0xA5 10100101 set 1 0xA7 10100111 clear 5 0x87 10000111 toggle 0 0x86 10000110 bit 7 is 1 2 && 1 = 1, 2 & 1 = 0
Fields and read-modify-write
A field of several bits is updated in two steps: clear it, then insert the new value, reg = (reg & ~MASK) | ((val << SHIFT) & MASK). On a hardware register, even |= is three steps: read, modify, write. If an interrupt changes the same register in between, its update is lost. Many MCUs therefore provide separate set and clear registers that change chosen bits in a single write; check your chip's reference manual.