Question

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.

Was it helpful?

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);

OTHER TIPS

Here's my solution for this exercise, I've added plenty comments for myself - hope someone will find it useful.

#include <stdio.h>

/* k&r exercise 2-6 */

int setbits(unsigned x, int p, int n, unsigned y);

int main(void) {
  setbits(218, 3, 3, 170);
}

/*
 * returns x with the n bits that begin at position p
 * set to rightmost n bits of y, leaving other bits
 * unchanged.
 *
 * all comments for setbits(218, 3, 3, 170)
 */
int setbits(unsigned x, int p, int n, unsigned y) {

  // get the mask for y - it is a n long mask.
  unsigned mask = ~0;           // 1111 1111
  mask = mask << n;     // shift n to get 1111 1000
  mask = ~mask;         // flip to get    0000 0111

  // AND y and the mask to 'delete' the bits that are not 1's
  // therefore extracting the desired n bits 
  y = y & mask;  // result 0000 0010 (decimal 2)

  // shift y p bits to the left to place the desired bit pattern where we need it
  // it will not be used until the last step though.
  y = y << p;

  // now we need to reuse the mask we've created earlier. reminder, currently
  // it is 0000 0111. we need to move the 1's to the left to 'aim' at the
  // spot we want to mask in x.
  mask = mask << p;

  // in order to keep the bits we want in x, we need to AND x with the inverted mask
  // inverting the mask:
  mask = ~mask;

  // &'ing x and mask:
  x = x & mask;

  // now finally, to insert the bit pattern we extracted from y, we need to OR
  // x and y.
  
  x = x | y;
  printf("%d\n", x); // expected: 210;

}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top