DSA MASTERY · CH 11 · BIT MANIPULATION · APPENDIX A
🐛 Debugging Bit Operations
Print binary · Common bug checklist · Operator precedence quick reference
Appendix A — practical tools and checklists for when your bit operations misbehave
A.1 — PRINT BINARY IN C AND JAVA
First step of debugging any bit bug: print what you actually have
Never guess at bit patterns in your head. Print them. Compare visually.// C — print binary for any unsigned integer, grouped by nibble
void printBits(uint64_t x, int bits) {
for (int i = bits-1; i >= 0; i--) {
putchar((x >> i) & 1 ? '1' : '0');
if (i > 0 && i % 4 == 0) putchar(' '); // group by nibble
}
putchar('\n');
}
// printBits(0xC0A80A05, 32):
// 1100 0000 1010 1000 0000 1010 0000 0101
// Alternative: use printf with format string
printf("x = 0x%08X = %u\n", x, x); // hex + decimal
// Java — print binary
System.out.println(Integer.toBinaryString(x)); // no leading zeros
System.out.printf("%32s%n", Integer.toBinaryString(x))
.replace(' ', '0'); // with leading zeros
System.out.println(Integer.toHexString(x)); // hex
System.out.println(Long.toBinaryString(x)); // 64-bit
✓ Debug workflow: Print both the mask and the value before ANDing. Print the result. Compare all three side-by-side in binary. The bug is usually immediately obvious visually.
A.2 — COMMON BUG CHECKLIST
| Bug | Example of the mistake | Fix |
|---|---|---|
| Missing parentheses | x & mask == 0 — parsed as x & (mask==0) |
(x & mask) == 0 |
| Sign extension on ~ | ~(uint8_t)x gives 32-bit result 0xFFFFFF00 |
(uint8_t)(~x) — cast after NOT |
| Shift by ≥ type width | 1 << 32 on int — undefined behaviour |
1ULL << 32 or use 64-bit type |
| Signed right shift | signed x >> n fills sign bit (arithmetic) |
Cast to unsigned, or use >>> in Java |
| No ntohs() before mask | Masking network-order bytes gives wrong fields on x86 | Always ntohs() / ntohl() before masking |
| Align not power of 2 | & (align-1) gives garbage if align=7 |
assert((align & (align-1)) == 0) at init |
| Ring size not pow2 | & mask wraps incorrectly |
Enforce nextPow2() at ring creation |
| Bit check vs exact match | if (x & mask) where mask has multiple bits — checks any, not all |
if ((x & mask) == mask) to require all bits set |
⚠️ Most frequent source of bit bugs: Missing parentheses around bitwise sub-expressions that are compared or combined with logical operators. When in doubt, add parentheses — they are free.
A.3 — OPERATOR PRECEDENCE QUICK REFERENCE (BITWISE CONTEXT)
Precedence (highest to lowest) — bitwise operators highlighted:
Priority | Operator(s) | Notes
-----------+----------------------+---------------------------------------
Highest | ~ | Bitwise NOT (unary) — applies first
| << >> | Shifts
| & | Bitwise AND
| ^ | Bitwise XOR
| | | Bitwise OR
-----------+----------------------+---------------------------------------
!!! TRAP | == != < > <= >= | Comparisons — ABOVE & ^ | ← GOTCHA!
-----------+----------------------+---------------------------------------
| && | Logical AND
| || | Logical OR
Lowest | = |= &= ^= <<= >>= | Assignment operators
| Expression | How it parses | What you meant |
|---|---|---|
x & 0xFF == 0 | x & (0xFF == 0) — always x & 0 | (x & 0xFF) == 0 |
a | b > 0 | a | (b > 0) — adds 0 or 1 | (a | b) > 0 |
flags & FLAG != 0 | flags & (FLAG != 0) — flags & 1 | (flags & FLAG) != 0 |
a ^ b == c | a ^ (b == c) — XOR with bool | (a ^ b) == c |
~x & mask | OK — ~ is highest bitwise | Fine as-is |
x << 2 & mask | OK — shifts before AND | Fine as-is |
✓ Golden rule: Wrap every bitwise sub-expression in parentheses when the result is used in a comparison or logical expression. The compiler will not warn you; the bug will be silent.
MASTERY CHECKLIST — BEFORE YOU SHIP BIT CODE
- All bitwise expressions mixed with comparisons have explicit parentheses
- NOT (~) on sub-int types is followed by an explicit cast back to the target type
- Shift amounts are < the width of the type (use ULL literals for 64-bit shifts)
- Signed types use >>> (Java) or explicit cast to unsigned (C) where logical shift needed
- All multi-byte network fields are converted with ntohs()/ntohl() before masking
- Alignment values are validated to be powers of 2 at initialisation
- Ring/hash table sizes are enforced to be powers of 2 before using &mask trick
- Printed binary representation validates every intermediate mask value