Sunday, 21 September 2025

Bit Manipulation in C: Set/Clear, Toggle, and Test Bits (With Tiny, Fast Utilities)

Working close to hardware means getting comfy with bits. Below are three tiny, production-ready C helpers you can drop into any project to set/clear a bit, toggle a specific bit, and check whether a bit is set. Each runs in constant time and uses simple masks—perfect for firmware, drivers, and competitive programming.


1) Set or Clear a Specific Bit (8-bit Register)

Goal: Given an 8-bit register value, a bit position (0–7), and a mode (1=set, 0=clear), return the updated value.

#include <stdio.h> #include <stdint.h> static inline uint8_t modify_bit(uint8_t reg, int pos, int mode) { if (mode) { reg |= (uint8_t)(1u << pos); // set bit } else { reg &= (uint8_t)~(1u << pos); // clear bit } return reg; } int main(void) { uint8_t reg; int pos, mode; if (scanf("%hhu %d %d", &reg, &pos, &mode) != 3) return 0; // (Optional) basic guardrails — ignore invalid input if (pos < 0 || pos > 7 || (mode != 0 && mode != 1)) { return 0; } printf("%u", (unsigned)modify_bit(reg, pos, mode)); return 0; }

How it works:

  • 1u << pos builds a mask for the target bit.

  • OR (|=) sets the bit; AND with NOT (&= ~) clears it.

  • Using uint8_t keeps the operation strictly 8-bit.


2) Toggle the 5th Bit (0-based)

Goal: Flip bit at position 5. XOR is your friend.

#include <stdio.h> static inline int toggle_fifth_bit(int n) { return n ^ (1 << 5); // XOR with 0b0010_0000 (32) } int main(void) { int n; if (scanf("%d", &n) != 1) return 0; printf("%d", toggle_fifth_bit(n)); return 0; }

Why XOR?

  • x ^ 1 flips a bit; x ^ 0 leaves it unchanged.

  • (1 << 5) targets only the 5th bit, so everything else stays intact.

Complexity: O(1) time, O(1) space.


3) Check if K-th Bit Is Set

Goal: Print 1 if the K-th bit of N is 1; else 0.

#include <stdio.h> static inline int is_kth_bit_set(int n, int k) { return (n & (1 << k)) ? 1 : 0; } int main(void) { int n, k; if (scanf("%d %d", &n, &k) != 2) return 0; printf("%d", is_kth_bit_set(n, k)); return 0; }

Why AND?

  • n & (1 << k) isolates that single bit. Non-zero → set; zero → clear.


Quick Notes & Best Practices

  • Prefer fixed-width types (uint8_t, uint32_t) for register-like code.

  • Validate input ranges when reading from users or untrusted sources.

  • When targeting 8-bit registers, cast masks to uint8_t to avoid surprises during promotion.


Conclusion

Bit operations are the bread-and-butter of embedded and systems work. With three tiny helpers—modify, toggle, and test—you can safely manipulate registers and flags with clean, constant-time code. Keep these patterns handy; they scale from toy examples to real device drivers.


Written By: Musaab Taha


This article was improved with the assistance of AI.



No comments:

Post a Comment