4

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

我一直试图在纸上处理这个功能一两个小时,但我没有得到任何结果。

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

示例:p = 7 n = 9以 x 作为顶场,y 是中间,结果是底场。

在此处输入图像描述


我无法确定如何使用任意大小的位字段来做到这一点。我应该使用sizeof(x) * 8还是没有必要?

我将不胜感激您可以提供有关如何实现此类功能的任何提示。

我还想知道这个练习的任何其他解释,可能是一个更容易的版本,尽管我确信这个可以完成。考虑到我花了多长时间,我希望能就此事发表第二意见,谢谢。

4

2 回答 2

4

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

由于这是C,假设最右边的位是#0,所以p = 0, n = 1意味着替换最右边的位x

你想做的是:

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

  2. 用位and掩码按位y提取最右边的ny并将其向左移动p

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

  4. 按位and反向移位位掩码,x以屏蔽要替换的位;

  5. 按位or计算 2 和 4 的结果来得到你的答案。

翻转以在代码中查看它:

int 位掩码 = ~((~0) << n);
返回 ((位掩码 & y) << p) | (~(位掩码 << p) & x);

于 2013-03-29T07:03:06.750 回答
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;

}
于 2021-01-22T03:07:19.263 回答