#include <stdio.h>
#include <stdint.h>
#include <limits.h>
#define MASK(pos, len) (((1ULL << (pos + len)) - 1) >> pos) << pos
uint32_t clear_bits(uint32_t reg, uint8_t pos, uint8_t len)
{
reg &= ~((uint32_t)MASK(pos, len));
return reg;
}
int main()
{
uint32_t reg;
uint8_t pos, len;
scanf("%u %hhu %hhu", ®, &pos, &len);
printf("%u", clear_bits(reg, pos, len));
return 0;
}This program is a professional-grade utility for clearing a specific range of bits within a 32-bit register. "Clearing" means forcing a selected group of bits to 0 while ensuring all other bits in the register remain exactly as they were.
The code uses a Negative Mask (often called an "Inverse Mask") to target a specific "window" of bits.
MASK(pos, len): This generates a sequence of 1s exactly where you want to clear the bits. For example, if pos=2 and len=3, the mask is 000...011100 (binary).
~ (Bitwise NOT): This operator flips every single bit in that mask.
The 1s (your target zone) become 0s.
The 0s (the protected zone) become 1s.
Result: 111...100011 (binary).
reg &= ...By using the Bitwise AND (&) with this inverted mask, the code achieves two things simultaneously:
In the Target Zone: Anything ANDed with 0 results in 0. This effectively "wipes" those bits.
In the Protected Zone: Anything ANDed with 1 stays the same (e.g., $1 \& 1 = 1$ and $0 \& 1 = 0$). This preserves the rest of the register.
Imagine you have a register controlling 8 LEDs. You want to turn off a group of 3 LEDs starting from position 2.
Input: reg = 255 (Binary: 11111111), pos = 2, len = 3.
Step | Operation | Binary Result |
|---|---|---|
1. Create Mask |
|
|
2. Invert Mask |
|
|
3. Apply AND |
|
|
Final Result | Value: 227 | Bits 2, 3, and 4 are now 0. |
Safety with 1ULL: The macro uses 1ULL (Unsigned Long Long) during the shift. This is a critical safety feature; if you try to shift a standard 32-bit 1 by 32 positions, it causes "undefined behavior" in C. Using a 64-bit constant prevents this crash.
Explicit Casting: In the function, (uint32_t)MASK ensures the 64-bit macro result is correctly sized back down to 32 bits before the bitwise NOT operation, preventing unexpected behavior with high-order bits.
Efficiency: This is a constant-time $O(1)$ operation. It doesn't matter if you are clearing 1 bit or 31 bits; it happens in a single CPU cycle.
Input
255 4 4
Expected Output
15