K& R练习2-6真正要求的功能是什么?

时间:2013-03-29 06:39:03

标签: kernighan-and-ritchie

  

练习2-6。写一个函数setbits(x,p,n,y),返回x,其中n位开头   位置p设置为y的最右边的n位,而其他位保持不变。

我一直试图在纸上乱搞这个功能一两个小时,而我却无处可去。

我解释该函数的方式是任意长度的位字段x是从最右边的位开始n位开始的p位。将这些n位更改为位于任意长度的位字段y中n最右位的相同位。

示例:p = 7 n = 9,其中x为顶部字段,y为中间,结果为底部字段。

enter image description here


我无法确定如何使用任意大小的位字段执行此操作。我应该使用sizeof(x) * 8还是不必要?

我很感激您可以提供的任何提示,以便人们如何能够发挥这样的作用。

我也想知道这个练习的任何其他解释,可能是一个可能更容易的版本,虽然我确信这个可以完成。考虑到我需要花多长时间,我会很感激第二个意见,谢谢。

2 个答案:

答案 0 :(得分:3)

由于xy是整数,您知道位字段的大小不能大于int中的位数。

由于这是C,假设最右边的位是#0,所以p = 0, n = 1表示替换x中最右边的位。

您想要做的是:

  1. 创建一个位掩码 - 最右边n位设置为1且其余为0的数字;

  2. 按位and使用y的位掩码提取n的最右侧y位并将其左移p位; < / p>

  3. 将位掩码p位向左移位以创建一个位掩码,该位掩码将从位置n开始的p位开始操作;

  4. 按位and使用x反向移位的位掩码来屏蔽要替换的位;

  5. 按位or得到2和4的结果。

  6. 翻转以在代码中查看:

      

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

答案 1 :(得分:1)

这是我对这个练习的解决方案,我为自己添加了很多评论 - 希望有人会觉得它有用。

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

}