I understand the basic bitwise operators, but I'm struggling to apply them without thinking through every bit one at a time. For example, I know that a mask such as 1 shifted left by a position can select a particular bit, but I'm unsure when to build masks dynamically and when a constant mask is simpler. Is a loop like this appropriate for examining every bit?
int size = sizeof(x) * 8;
int mask = 1;
for (int i = 0; i < size; i++) {
/* operate on x using mask */
mask <<= 1;
}
I'd also like to understand practical techniques for swapping two individual bits, or exchanging groups of bits such as the upper and lower four bits of a byte. My first thought was to extract both bits into temporary variables, clear their original positions, and then insert them again, but that feels overly complicated. What are the usual shortcuts and patterns for these operations?
5 Answers
One useful way to think about bit manipulation is: select with AND, clear with AND plus a complemented mask, set with OR, and toggle with XOR. Shifts move the selected bits into or out of position. Once you separate those steps, most bit operations become a combination of a mask, a shift, and one logical operation rather than a bit-by-bit procedure.
For swapping two bits at positions a and b, first check whether they differ. If they do, toggling both positions swaps them; if they are equal, toggling both would be pointless.
if (((n >> a) & 1) != ((n >> b) & 1))
n ^= (1 << a) | (1 << b);
This works because XOR with a mask containing two 1 bits flips exactly those positions. If the selected bits are 00 or 11, they remain unchanged; if they are 01 or 10, they become 10 or 01.
To test a particular bit, create a mask with a 1 in that position and AND it with the value. For example, bit position 2 uses 1 << 2, which is 0x04:
int bit = (value & (1 <> 2) & 1. You generally only need a loop when the bit positions are determined at runtime or you truly need to inspect every bit.
The explicit approach is to extract each bit, clear both original positions, shift the extracted values, and OR them back in. For two positions, the pattern is:
unsigned mask = (1u << a) | (1u <> a) & 1u;
unsigned bBit = (n >> b) & 1u;
n = (n & ~mask) | (aBit << b) | (bBit <> 4) | (x << 4);
For a byte, the shifts discard the parts outside the byte’s range; using a uint8_t or masking the result makes the intended width explicit. More generally, a mask can represent many bits, so you do not need a temporary variable for each individual bit.
Your loop idea is valid for walking through all bits, but use an unsigned type and a width based on the type rather than assuming int has exactly 8 bits per byte. In C, CHAR_BIT gives the number of bits in a byte, and size_t is the appropriate type for sizes. For fixed-width data such as uint8_t, uint16_t, or uint32_t, the width is known.
For fixed operations, constant masks are usually clearer: 0x0F selects the low four bits, 0xF0 selects the high four bits, and (1u << position) selects one bit. Build masks dynamically only when the selected positions or field widths come from input or another runtime value.

Also be careful with the wording: AND with zero clears a bit, OR with one sets it, XOR with one toggles it, and XOR with zero leaves it unchanged. Those operations are different even though some of their effects may sound similar.