kernighan-and-ritchie

What function is K&R exercise 2-6 really asking for?


Exercise 2-6. Write a function setbits(x,p,n,y) that returns x with the n bits that begin at position p set to the rightmost n bits of y, leaving the other bits unchanged.

I have been trying to mess around with this function on paper for a good hour or two, and I am not getting anywhere.

The way I interpret the function is that a bit field, x, of arbitrary length is to look at it's n bits starting p places from the right-most bit. Change these n bits to the same bits located in the n right-most bits in a bit field, y, of arbitrary length.

Example: p = 7 n = 9 with x as the top field, y is the middle, the result is the bottom field.

enter image description here


I am having trouble determining how I could do this with arbitrary sized bit fields. Should I use sizeof(x) * 8 or is this unnecessary?

I would appreciate any hints you can provide to how one can make such a function.

I would also like to know any other interpretations of the exercise, possibly a version that may be easier although I am sure this one can be done. Given how long it is taking me I would appreciate a second opinion on the matter, thanks.


Solution

  • Since x and y are ints, you know that the size of the bit field can be no larger than the number of bits in an int.

    Since this is C, assume that the right-most bit is #0, so p = 0, n = 1 means to replace the right-most bit in x.

    What you want to do is:

    1. create a bitmask -- a number with the right-most n bits set to 1 and all the rest 0;

    2. bitwise and the bitmask with y to extract the right-most n bits of y and shift it left p bits;

    3. shift the bitmask p bits to the left to create a bitmask that will operate on n bits starting at position p;

    4. bitwise and the inverse shifted bitmask with x to mask out the bits you want to replace;

    5. bitwise or the result of 2 and 4 to get your answer.

    Rollover to see it in code:

    int bitmask = ~((~0) << n);
    return ((bitmask & y) << p) | (~(bitmask << p) & x);