๐Ÿ”ข 19. Bitwise Programming

CodeBhavya Rule: In bitwise code, clarity beats cleverness. First write the mask, then explain which bit it selects, then perform the operation.

Do not rely on memory alone when an expression becomes complicated. Parentheses make the intended operation visible to both the compiler and the reader.

if ((flags & MASK) != 0) {
    /* selected bit is set */
}

Bitwise expressions can become difficult to read when mixed with arithmetic, relational, and logical operators. Use parentheses when the intended grouping is important.

19.31 Important Operator Precedence

  • Confusing bitwise and logical operators.
  • Forgetting that bit positions normally start at 0.
  • Using a shift count that is invalid for the operand width.
  • Assuming signed right shift always behaves the same on every implementation.
  • Using signed values when unsigned masks would make the intent clearer.
  • Forgetting integer promotions when using small integer types such as unsigned char.
  • Writing masks with the wrong type or width.
  • Assuming ~x simply means โ€œmake x negativeโ€. It flips bits; the resulting value is then interpreted as an integer.
  • Using the XOR swap trick when both operands refer to the same object.

19.30 Common Bitwise Mistakes

Common interview trap: & is not the same as &&, and | is not the same as ||.
BitwiseLogical
&, |, ^, ~&&, ||, !
Works on bit patternsWorks with truth conditions
5 & 3 โ†’ 15 && 3 โ†’ 1
Usually does not mean โ€œtrue/falseโ€Produces a logical truth result

19.29 Bitwise vs Logical Operators

For portable code, choose the width from the actual unsigned type rather than hard-coding an assumption when possible.

for (int i = width - 1; i >= 0; i--)
    printf("%u", (value >> i) & 1u);

To print an unsigned integer in binary, inspect each bit from the most significant position toward the least significant position.

19.28 Print a Binary Representation

This is one of the most practical real-world uses of bitwise programming.

flags |= READ_FLAG;      /* set */
flags &= ~READ_FLAG;     /* clear */
flags ^= READ_FLAG;      /* toggle */

if (flags & READ_FLAG)   /* test */
    printf("Enabled");

19.27 Set, Clear and Toggle a Flag

This technique can represent multiple Boolean settings compactly inside one value.

#define READ_FLAG   (1u << 0)
#define WRITE_FLAG  (1u << 1)
#define EXEC_FLAG   (1u << 2)

One integer can store several independent yes/no states. Each bit represents one flag.

19.26 Using Bits as Flags

result = 0;
for (i = 0; i < n; i++)
    result ^= a[i];
  • x ^ x = 0
  • x ^ 0 = x
  • XOR is associative and commutative.

If every value occurs exactly twice except one value, XOR can isolate the unique value because:

19.25 Find the Unique Element Using XOR

Important: this is mainly a bitwise exercise/interview technique. A temporary variable is usually clearer in normal application code, and the XOR trick must not be used when both expressions refer to the same object.
a ^= b;
b ^= a;
a ^= b;

XOR can swap two integer values without a third variable:

19.24 Swap Two Values Using XOR

Use the technique deliberately and keep the signed/unsigned type rules in mind.

lowest = value & -value;

For unsigned integers, the more familiar equivalent is:

lowest = value & (~value + 1);

To keep only the lowest set bit:

19.23 Isolate the Lowest Set Bit

This is the same operation used by the efficient set-bit counting algorithm.

value = value & (value - 1);

The expression below removes the lowest 1-bit:

19.22 Clear the Lowest Set Bit

Why? Subtracting 1 changes the single set bit to 0 and turns lower zeros into 1s, so AND produces zero.
value != 0 && (value & (value - 1)) == 0

For a positive unsigned integer, a power of two has exactly one set bit.

19.21 Check Whether a Number Is a Power of 2

Each iteration eliminates one 1-bit, so the loop runs once per set bit rather than once per bit position.

while (value != 0) {
    value = value & (value - 1);
    count++;
}

A classic technique removes the lowest set bit in each iteration:

19.20 Efficient Set-Bit Counting

This is easy to understand and demonstrates how binary positions can be processed one at a time.

count = 0;
while (value != 0) {
    count += value & 1u;
    value >>= 1;
}

A set bit is a bit whose value is 1. The simple approach repeatedly checks the lowest bit and shifts the value:

19.19 Count Set Bits

Test
value & mask
Set
value | mask
Toggle
value ^ mask
Clear
value & ~mask

Think of the mask as a set of switches identifying exactly which bits an operation should affect.

1u << 3  โ†’ 00001000

A mask is a carefully chosen bit pattern used to select or modify specific positions.

19.18 Bit Mask โ€” The Central Bitwise Technique

XOR is ideal because XOR with 1 flips a bit, while XOR with 0 leaves it unchanged.

value = value ^ (1u << k);

Toggle means 0 becomes 1 and 1 becomes 0:

19.17 Toggle a Bit

The mask is first inverted so every other position remains 1 while the selected position becomes 0.

value = value & ~(1u << k);

Clearing a bit means forcing it to 0:

19.16 Clear a Bit

OR is used because a 1 in the mask turns the selected bit on.

value = value | (1u << k);

Setting a bit means forcing it to 1 without changing the other bits:

19.15 Set a Bit

Bit positions start at 0 from the least significant bit.

mask = 1u << k;
if (value & mask)
    /* bit k is set */

To test bit position k, build a mask with only that bit set:

19.14 Check Whether a Bit Is Set

10 = 1010   โ†’ 10 & 1 = 0
11 = 1011   โ†’ 11 & 1 = 1
  • Result 0 โ†’ even
  • Result 1 โ†’ odd
number & 1

The least significant bit tells whether a nonnegative integer is odd or even.

19.13 Check Odd or Even Using Bitwise AND

Placement rule: before shifting, know the type, its width, and whether the value is signed or unsigned.
  • The right operand must be nonnegative.
  • Its value must be less than the width in bits of the promoted left operand.
  • Do not assume signed shifts behave like mathematical multiplication or division for every value.
  • Use unsigned integers when implementing masks and bit fields that require predictable binary behavior.

19.12 Important Shift Rules

For unsigned values, zero bits are shifted in from the left. For negative signed values, the result of right shift is implementation-defined, so use unsigned types when you need predictable bit manipulation.

20      = 00010100
20 >> 1 = 00001010 = 10
20 >> 2 = 00000101 = 5

A right shift moves bits toward lower positions. Bits shifted out on the right are discarded.

19.11 Right Shift >>

For nonnegative values, a left shift by n often corresponds to multiplying by 2^n, but shift expressions must still respect C's type and undefined-behavior rules.

5       = 00000101
5 << 1  = 00001010 = 10
5 << 2  = 00010100 = 20

A left shift moves bits toward higher positions and inserts zeros into the vacated low-order positions.

19.10 Left Shift <<

Do not confuse: ~ is bitwise NOT; ! is logical NOT. They solve completely different problems.
For the usual twoโ€™s-complement signed representation:
~x = -x - 1

Therefore: ~5 = -5 - 1 = -6

The resulting bit pattern represents -6 in twoโ€™s complement.

 5  = 00000000 00000000 00000000 00000101
~5  = 11111111 11111111 11111111 11111010

NOT flips every bit. For a signed C integer, the result must also be interpreted using the representation of signed integers on the implementation. On the usual twoโ€™s-complement representation:

19.9 Bitwise NOT ~ โ€” Why Does ~5 Become -6?

ABA ^ B
000
011
101
110

19.8 XOR Truth Table

XOR memory rule: same โ†’ 0, different โ†’ 1.

So 12 ^ 10 produces 6.

12 = 1100
10 = 1010
     ----
^    0110 = 6

XOR produces 1 when the two corresponding bits are different.

19.7 Bitwise XOR ^

So 12 | 10 produces 14.

12 = 1100
10 = 1010
     ----
|    1110 = 14

OR produces 1 when at least one corresponding bit is 1.

19.6 Bitwise OR |

Common use: AND with a mask to test or clear selected bits.
ABA & B
000
010
100
111

19.5 AND Truth Table

So 12 & 10 produces 8.

12 = 1100
10 = 1010
     ----
&    1000 = 8

AND examines corresponding bits and produces 1 only when both input bits are 1.

19.4 Bitwise AND &

OperatorNameWorks onMain idea
&ANDEach pair of bits1 only when both bits are 1
|OREach pair of bits1 when at least one bit is 1
^XOREach pair of bits1 when the bits are different
~NOTEach bitFlips every bit
<<Left shiftBits of a valueMoves bits toward higher positions
>>Right shiftBits of a valueMoves bits toward lower positions

19.3 The Bitwise Operators

For example, 10 is 00001010 because 8 + 2 = 10.

Bit76543210
Weight1286432168421

For an 8-bit unsigned value, each position represents a power of 2:

19.2 Binary Representation โ€” The Foundation

Think of it this way: arithmetic usually asks โ€œwhat is the value?โ€, while bitwise programming asks โ€œwhat is happening to each binary position?โ€

Bitwise operations are especially useful when a program needs compact flags, masks, device control, binary protocols, permissions, or low-level data manipulation.

Decimal value โ†’ Binary representation โ†’ Individual bits โ†’ Bitwise operation โ†’ Result

Bitwise programming works directly with the individual bits of an integer. Each bit is either 0 or 1.

19.1 What Is Bitwise Programming?

19.32 Quick Revision

๐Ÿ“Œ & โ†’ AND

๐Ÿ“Œ | โ†’ OR

๐Ÿ“Œ ^ โ†’ XOR

๐Ÿ“Œ ~ โ†’ NOT

๐Ÿ“Œ << โ†’ Left shift

๐Ÿ“Œ >> โ†’ Right shift

๐Ÿ“Œ n & 1 โ†’ Check least significant bit

๐Ÿ“Œ n | (1u << k) โ†’ Set bit

๐Ÿ“Œ n & ~(1u << k) โ†’ Clear bit

๐Ÿ“Œ n ^ (1u << k) โ†’ Toggle bit

๐Ÿ“Œ n & (n - 1) โ†’ Remove lowest set bit

๐Ÿ“Œ n & (n - 1) == 0 โ†’ Power-of-two test when n is positive
INTERACTIVE LEARNING

๐ŸŽฌ Bitwise Programming โ€” Bit Mask Flow

Follow how a mask is created, used to check a selected bit, and then used to set that bit.

PROGRAM TRACING

๐Ÿ”Ž Program Tracing โ€” Bitwise Programming

Trace mask creation, checking a bit, and setting the selected bit.

19.33 Quick MCQs

Select an answer first, then click Check Answer. A correct choice becomes green. If the answer is wrong, your choice becomes red and the correct option becomes green. The explanation appears below.

1. Which operator performs bitwise AND?
2. Which operator performs bitwise XOR?
3. Which operator flips bits?
4. What is 5 & 3?
5. What is 5 | 3?
6. What is 5 ^ 3?
7. Which operator performs left shift?
8. Which expression checks whether bit k is set?
9. Which expression sets bit k?
10. Which expression removes the lowest set bit?
PRACTICE

19.34 ๐ŸŽฏ Practice Problems

Practice AND, OR, XOR, NOT, shifts, bit masks, set-bit counting, powers of two, flags, and XOR-based array problems. Use ๐Ÿ’ป Solve It Yourself first, open Hint only when needed, and use Show Program after attempting the problem.

๐Ÿ“ˆ Bitwise Programming Practice Progress
Solved 0 / 20
Completed with Solution 0
Total Score 0 / 2000
Completion 0%
A problem counts as Solved when all test cases pass without opening the full solution. Problems completed after viewing the official solution are tracked separately.
1. Bitwise AND of Two Integers

Problem 1: Find the result of bitwise AND for two unsigned integers.

Input: Two unsigned integers a and b.

Output: Print a & b.

2. Bitwise OR of Two Integers

Problem 2: Find the result of bitwise OR for two unsigned integers.

Input: Two unsigned integers a and b.

Output: Print a | b.

3. Bitwise XOR of Two Integers

Problem 3: Find the result of bitwise XOR for two unsigned integers.

Input: Two unsigned integers a and b.

Output: Print a ^ b.

4. Bitwise NOT of a 32-bit Integer

Problem 4: Find the bitwise NOT of a 32-bit unsigned integer.

Input: One uint32_t value.

Output: Print the 32-bit unsigned complement.

5. Left Shift by One Position

Problem 5: Perform a left shift by one position on a 32-bit unsigned integer.

Input: One uint32_t value whose result fits in 32 bits.

Output: Print n << 1.

6. Right Shift by Two Positions

Problem 6: Perform a right shift by two positions on an unsigned integer.

Input: One unsigned integer n.

Output: Print n >> 2.

7. Odd or Even Using Bitwise AND

Problem 7: Check whether an integer is odd or even using bitwise AND.

Input: One integer n.

Output: Print "Odd" or "Even".

8. Check Whether the kth Bit is Set

Problem 8: Check whether bit k is set in a 32-bit unsigned integer.

Input: n and k, where 0 <= k < 32.

Output: Print "Set" or "Not Set".

9. Set the kth Bit

Problem 9: Set bit k of a 32-bit unsigned integer.

Input: n and k, where 0 <= k < 32.

Output: Print the modified value.

10. Clear the kth Bit

Problem 10: Clear bit k of a 32-bit unsigned integer.

Input: n and k, where 0 <= k < 32.

Output: Print the modified value.

11. Toggle the kth Bit

Problem 11: Toggle bit k of a 32-bit unsigned integer.

Input: n and k, where 0 <= k < 32.

Output: Print the modified value.

12. Count Set Bits

Problem 12: Count the number of set bits in a 32-bit unsigned integer using repeated bit checks.

Input: One uint32_t value.

Output: Print the number of 1 bits.

13. Brian Kernighan Set-Bit Count

Problem 13: Count set bits using Brian Kernighan's algorithm.

Input: One uint32_t value.

Output: Print the number of set bits.

14. Check Whether a Number is a Power of 2

Problem 14: Check whether a positive unsigned integer is a power of 2.

Input: One unsigned integer n.

Output: Print "Power of 2" or "Not Power of 2".

15. Find the Unique Element

Problem 15: Find the unique element in an integer array where every other element appears exactly twice.

Input: n followed by n integers.

Output: Print the unique element.

16. Print Binary Representation

Problem 16: Print the 32-bit binary representation of an unsigned integer.

Input: One uint32_t value.

Output: Print exactly 32 bits from bit 31 down to bit 0.

17. Swap Two Integers Using XOR

Problem 17: Swap two unsigned integers using XOR without a temporary variable.

Input: Two unsigned integers a and b.

Output: Print the swapped values.

18. Set, Clear and Toggle a Selected Bit

Problem 18: Given n and k, print the results of setting, clearing, and toggling bit k.

Input: A uint32_t n and bit position k, where 0 <= k < 32.

Output: Print Set, Clear, and Toggle results on separate lines.

19. Permission System Using Bit Flags

Problem 19: Implement READ, WRITE, and EXECUTE permissions using bit flags. Start with no permissions, apply three requested operations, then print the final permissions.

Input: Three integers: readFlag writeFlag executeFlag, each 0 or 1.

Output: Print permissions in the form READ=Yes/No WRITE=Yes/No EXECUTE=Yes/No.

20. Find Two Unique Numbers

Problem 20: Given an array where every number appears twice except two numbers, find those two unique numbers using bitwise operations.

Input: n followed by n integers. Exactly two values occur once; all others occur twice.

Output: Print the two unique values in ascending order.

19.35 Key Takeaway

๐ŸŽฏ Remember:

AND (&) โ†’ Select bits

OR (|) โ†’ Set bits

XOR (^) โ†’ Toggle / find differences

NOT (~) โ†’ Flip bits

Left Shift (<<) โ†’ Move bits left

Right Shift (>>) โ†’ Move bits right

n & 1 โ†’ Check odd/even

n & (n - 1) โ†’ Remove lowest set bit

1u << k โ†’ Create a mask for bit k
INTERVIEW PREPARATION

๐ŸŽค Bitwise Programming โ€” Interview Questions

1. What is the difference between bitwise & and logical &&?
2. Why are unsigned integers often preferred for bit manipulation?
3. How do you check whether bit k is set?
4. How do you clear bit k without changing other bits?
5. Why does n & (n - 1) remove the lowest set bit?
6. How can XOR find one unique element when all others appear twice?
7. How do bit flags represent multiple permissions?
8. What shift mistake should be avoided?
PLACEMENT TIPS

๐Ÿ’ก Bitwise Programming โ€” Placement Tips

  • For bit-position problems, write the mask first: 1u << k. Then decide whether the task needs &, |, ^, or ~.
  • Prefer unsigned values when a problem is specifically about binary representation and bit manipulation.
  • Remember the three core mask formulas: set with |, clear with & ~mask, and toggle with ^.
  • For power-of-two questions, handle zero separately before using n & (n - 1).
  • XOR is especially useful when duplicate values occur in pairs because equal values cancel.
  • Be careful with operator precedence; add parentheses around bitwise expressions when combining them with comparisons or arithmetic.
EXTRA PRACTICE

โœ๏ธ Bitwise Programming โ€” Extra Practice Questions

  1. Find the position of the lowest set bit in a positive integer.
  2. Reverse all 32 bits of an unsigned integer.
  3. Check whether two integers have opposite signs using a bitwise expression.
  4. Generate every subset of a small array using bit masks.
  5. Find the missing number from 0 to n using XOR.
  6. Implement a compact feature-control system using eight independent bit flags.
โ† Previous Topic: Command Line Arguments Next Topic: Enumerations & typedef โ†’