练习2-6。写一个函数setbits(x,p,n,y),返回x,其中n位开头 位置p设置为y的最右边的n位,而其他位保持不变。
我一直试图在纸上乱搞这个功能一两个小时,而我却无处可去。
我解释该函数的方式是任意长度的位字段x是从最右边的位开始n
位开始的p
位。将这些n
位更改为位于任意长度的位字段y中n
最右位的相同位。
示例:p = 7
n = 9
,其中x为顶部字段,y为中间,结果为底部字段。
我无法确定如何使用任意大小的位字段执行此操作。我应该使用sizeof(x) * 8
还是不必要?
我很感激您可以提供的任何提示,以便人们如何能够发挥这样的作用。
我也想知道这个练习的任何其他解释,可能是一个可能更容易的版本,虽然我确信这个可以完成。考虑到我需要花多长时间,我会很感激第二个意见,谢谢。
答案 0 :(得分:3)
由于x
和y
是整数,您知道位字段的大小不能大于int中的位数。
由于这是C,假设最右边的位是#0,所以p = 0, n = 1
表示替换x
中最右边的位。
您想要做的是:
创建一个位掩码 - 最右边n
位设置为1且其余为0的数字;
按位and
使用y
的位掩码提取n
的最右侧y
位并将其左移p
位; < / p>
将位掩码p
位向左移位以创建一个位掩码,该位掩码将从位置n
开始的p
位开始操作;
按位and
使用x
反向移位的位掩码来屏蔽要替换的位;
按位or
得到2和4的结果。
翻转以在代码中查看:
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;
}