How do I build bit masks and swap individual bits or groups of bits?
Asked by
MellowPine42
I understand the basic bitwise operators, but I struggle to use them for practical tasks. How do I create masks, inspect a number one bit at a time, and decide when iteration is actually necessary? For example, is a loop using a shifting mask appropriate for examining every bit in an integer, and what types should be used for the size calculation in C?
I also want to understand how to swap two individual bits, or exchange groups of bits such as the upper and lower four bits of a byte. My initial idea was to extract each bit into temporary variables and then clear and set the target positions, but that seems more complicated than necessary. What are the standard techniques and useful shortcuts for these operations?
Answers
To swap two bits at positions a and b, first check whether they differ. If they do, toggling both positions exchanges them:
`if (((value >> a) & 1u) != ((value >> b) & 1u))`
` value ^= (1u << a) | (1u << b);`
If the bits are equal, toggling both would leave the value unchanged anyway, so the conditional can also be omitted when that behavior is acceptable.
Reply to this answer
The explicit approach is to extract both bits, clear those positions, shift the extracted values into their opposite positions, and OR them back in:
`unsigned mask = (1u << a) | (1u <> a) & 1u;`
`unsigned bitB = (value >> b) & 1u;`
`value = (value & ~mask) | (bitA << b) | (bitB << a);`
This is longer but useful for understanding what is happening: clear the destination positions, then insert the moved bits.
Reply to this answer
To test a bit at position p, use `(value & (1u << p)) != 0`. The mask has a 1 only at that position, so the result is zero when the bit is clear and nonzero when it is set. You usually do not need to construct masks bit by bit unless the positions are determined dynamically. If you do scan every bit, use an unsigned type and a mask such as `1u << i`; for a portable size calculation in C, prefer `sizeof(value) * CHAR_BIT` and an appropriate `size_t` variable.
Reply to this answer
For exchanging the two four-bit halves of an 8-bit value, mask each half and shift it into the other position:
`value = ((value & 0xf0u) >> 4) | ((value & 0x0fu) <> 4) | (value << 4)`. Masks are not limited to one bit; a mask such as `0xf0` selects a whole group.
Reply to this answer
Add your answer
Answers are reviewed before publication.
Related Discussions