#include <stdio.h>
#include <stdint.h>
#include <limits.h>
#define MASK(pos, len) (((1ULL << (pos + len)) - 1) >> pos) << pos
uint32_t replace_field(uint32_t reg, uint32_t val, uint8_t pos, uint8_t len)
{
uint32_t rpl_val = (val & ((1 << len) - 1)) << pos;
reg &= ~((uint32_t)MASK(pos, len));
reg |= rpl_val;
return reg;
}
int main()
{
uint32_t reg, val;
uint8_t pos, len;
scanf("%u %u %hhu %hhu", ®, &val, &pos, &len);
printf("%u", replace_field(reg, val, pos, len));
return 0;
}This code is a high-level utility for Read-Modify-Write operations. It allows you to take a specific "slice" or "field" inside a 32-bit register and replace it with a new value without disturbing any of the surrounding bits.
To replace a bit-field safely, the program follows a "Clear then Insert" strategy:
1. Prepare the New Value (rpl_val)
uint32_t rpl_val = (val & ((1 << len) - 1)) << pos;
Sanitize: It first masks the input val to ensure it isn't larger than the allowed len. This prevents the new value from "bleeding" into neighboring fields.
Align: It shifts the sanitized value to the left by pos so it sits exactly where it needs to go in the register.
2. Clear the Target Area
reg &= ~((uint32_t)MASK(pos, len));
Before inserting the new bits, the code must "clean" the destination. It uses an inverted mask to force the bits in the target range to 0.
Think of this as erasing a whiteboard before writing a new message.
3. Insert the Value
reg |= rpl_val;
Finally, it uses the Bitwise OR (|) to merge the new aligned value into the now-empty slot in the register.
Imagine a register controlling a motor's speed in bits 4 to 6 (length 3).
Current Register: 242 (Binary: 1111 0010). Note that speed bits [6:4] are 111 (7).
New Speed Value: 2 (Binary: 010).
Goal: Change speed from 7 to 2 at position 4.
Step | Operation | Result (Binary) |
|---|---|---|
Initial |
|
|
Clear |
|
|
Align |
|
|
Merge |
|
|
Final | Result: 162 | Speed is now 2, other bits are untouched. |
Atomic-like Updates: In embedded systems (like controlling an ECU or a GPIO pin), you often need to change one setting (like "Baud Rate") without accidentally changing another (like "Enable Pin"). This code ensures that "surgical" precision.
Input Protection: The (val & ((1 << len) - 1)) part is a critical safety feature. If a user tries to put a 4-bit value into a 2-bit field, the code clips the extra bits instead of corrupting the rest of the register.
Efficiency: This avoids slow if-else logic or loops. It uses pure bitwise math, which the CPU can execute in a fraction of a nanosecond.
pos: The starting bit index (0–31).
len: How many bits the field occupies.
val: The new data you want to put into that field.
Input
255 0 4 4
Expected Output
15