summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ch2/2-6.c18
1 files changed, 11 insertions, 7 deletions
diff --git a/ch2/2-6.c b/ch2/2-6.c
index ee6770d..0932206 100644
--- a/ch2/2-6.c
+++ b/ch2/2-6.c
@@ -1,15 +1,19 @@
#include<stdio.h>
+/*
+ * Set n bits in x starting at position p to rightmost n bits of y.
+ */
+
unsigned setbits(unsigned x, unsigned p, unsigned n, unsigned y) {
- // set n bits in x starting at p to rightmost n bits of y
- unsigned offset = (p + 1 - n);
- unsigned y_mask = y & ~(~0 << n);
- unsigned bot = x & ~(~0 << offset);
- unsigned top = (x >> offset << offset) & y_mask;
- unsigned result = top & bot;
- return result;
+ p++; // We're actually interested in p+1.
+ unsigned offset = (p - n); // Calculate offset of y bits being inserted into x.
+ unsigned lower_x = x & ~(~0 << offset); // Grab LSBs of x to save.
+ unsigned y_mask = (y & ~(~0 << n)) << offset; // Grab pattern from LSBs of y.
+ x = x >> p << p; // Just keep MSBs of x.
+ return x | y_mask | lower_x; // Concatenate MSBs of x with LSB pattern from y with LSBs of x.
}
int main() {
printf("%x\n", setbits(0xaa, 3, 3, 0x33));
+ printf("%x\n", setbits(0x00, 3, 3, 0xff));
}