
In the world of embedded systems, bit manipulation is more than just a trick—it is the language of hardware. Whether you are toggling a GPIO pin or optimizing a driver for memory-constrained environments, mastering these operations is non-negotiable for any serious developer.
This guide covers the fundamental operations, the “must-memorize” logic tricks, and the common problems you will face in technical interviews.
Every interview starts here. These four macros are the building blocks of register-level programming.
#define SET_BIT(n, i) ((n) | (1U << (i))) // Set bit i to 1#define CLEAR_BIT(n, i) ((n) & ~(1U << (i))) // Set bit i to 0#define TOGGLE_BIT(n, i) ((n) ^ (1U << (i))) // Flip bit i#define CHECK_BIT(n, i) (((n) >> (i)) & 1U) // Get bit i (0 or 1)
These specific logic patterns are common “whiteboard” questions because they demonstrate a deep understanding of binary arithmetic.
| Trick | Code | Use Case |
|---|---|---|
| Clear rightmost 1-bit | n & (n-1) | Check power of 2, count set bits |
| Get rightmost 1-bit | n & (-n) | Find least significant set bit |
| Toggle bits | n ^ mask | Flip bits based on a specific pattern |
n & (n-1)This operation always clears the lowest set bit.
(n > 0) && ((n & (n-1)) == 0), it is a power of 2.int countSetBits(uint32_t n) {int count = 0;while (n > 0) {n = n & (n-1); // Clear one bit each timecount++;}return count;}
The XOR operator (^) is unique because a ^ a = 0 and a ^ 0 = a.
void swap(int *x, int *y) {if (x != y) { // Critical safety check*x ^= *y;*y ^= *x;*x ^= *y;}}
Warning: This will fail if
aandbpoint to the same memory location, as it will clear the value to 0!
In an array containing numbers from 1 to n with one number missing, you can XOR all numbers in the array and then XOR the result with all numbers from 1 to n. The final result is the missing number.
For advanced hardware configurations, you often need to manipulate bit fields or check status flags.
#include <stdint.h>// Get n bits starting from position p (0-indexed)uint32_t getBits(uint32_t num, int p, int n) {// Avoid shifting by full width of type (Undefined Behavior)uint32_t mask = (n == 32) ? 0xFFFFFFFF : (1U << n) - 1;return (num >> (p - n + 1)) & mask;}// Set n bits starting from position p with bits from valuint32_t setBits(uint32_t num, int p, int n, uint32_t val) {uint32_t mask = (n == 32) ? 0xFFFFFFFF : (1U << n) - 1;uint32_t shift_amount = (p - n + 1);// 1. Clear the target bits in num// 2. Mask val to ensure only n bits are used, then shift itreturn (num & ~(mask << shift_amount)) | ((val & mask) << shift_amount);}
int oppositeSigns(int x, int y) {return ((x ^ y) < 0); // True if different sign bits}
Prepare for these common coding challenges:
(n << d) | (n >> (32 - d)).if statements with masks to find the first set bit.Copy this card into your notes for a quick pre-interview refresh:
| Operation | C Code Snippet |
|---|---|
| Set bit i | n \| (1U << i) |
| Clear bit i | n & ~(1U << i) |
| Toggle bit i | n ^ (1U << i) |
| Check bit i | (n >> i) & 1U |
| Clear lowest set bit | n & (n-1) |
| Get lowest set bit | n & (-n) |
| Count set bits | n & (n-1) loop |
| Check power of 2 | (n > 0) && ((n & (n-1)) == 0) |
| Swap a and b | a ^= b; b ^= a; a ^= b; |
| Absolute value | (n ^ (n>>31)) - (n>>31) |
| Opposite Signs | (x ^ y) < 0 |
Remember for the computation (n ^ (n>>31)) - (n>>31) : This trick relies on Arithmetic Right Shift (filling with the sign bit). In C, right-shifting a signed negative integer is implementation-defined. If the compiler does a logical shift (filling with 0), this code breaks.
For the computation a ^= b; b ^= a; a ^= b; : a and b should not be at the same address.
Found this guide helpful? Share it with your fellow engineers and good luck with your interview!
Quick Links
Legal Stuff




