源自《The C Programming Language》P40 pr2-6:
编写一个函数setbits(x, p, n, y),该函数返回对x执行下列操作后的结果值:将x中从第p位开始的n个(二进制)位设置为
y中最右边n位的值,x的其余各位保持不变。
代码:
#include
unsigned setbits(unsigned x, int p, int n, unsigned y);
int main()
{
unsigned num = 125;//待处理的十进制数
int pos = 7;//从数1的第pos位开始(从右至左)
int cnt = 4;//处理字段的长度
unsigned numset = 65;//被获取某个字段的十进制数
printf("%u/n", setbits(num, pos, cnt, numset));
return 0;
}
/********************************************************
**函数名称:setbits
** 功能:将x中从第p位开始的n个位设置成y中最右边n位的值,
** x的其余各位保持不变
** 参数:x:待处理的数
**p:从y中获取的字段放入x中的开始位置
**n:从y中获取的字段的长度
**y:被获取字段的数
**返回值:x中第p位开始长度为n的二进制位被替代成y的最右n
** 个字段的值,其他位保持不变,然后返回这个结果。
**/
unsigned setbits(unsigned x, int p, int n, unsigned y)
{
unsigned tmp;
tmp = (~0 << p+1) | ~(~0 << p+1-n);//tmp:从第p位开始,长度为n,其中位值为0,其余
//位值为1的二进制数--此处用十进制数来表示。
x = x & tmp;//将x中的第p位开始长度为n的位值置为0,其余不变。
y = (y << p+1-n) & ~tmp;//将y左移p+1-n位,然后与~tmp相与,这样y的从第p
//位开始,长度为n的位的值即为操作前的y的最右n位
//的值,而此时y的其余位的值为0。
return x | y;//将操作后的x,y相与,即实现功能。
}
分析:
1, 分析setbits(x, p, n, y)函数:
假设,x = 11010010,p = 5,n = 4,y = 01011101,
~0 << p+1 //将11111111左移6位,得到11000000
~(~0 << p+1-n) //将11111111左移2位,得到11111100,然后求反,结果为00000011
tmp = (~0 << p+1) | ~(~0 << p+1-n) //将11000000 | 00000011 = 11000011
这样得到一个从第p(5)位开始长度为n(4)的位值为0,其余值为1的二进制数,用它来将x中相应的位的值置为0。
x = x & tmp; //将x中从第p位开始,长度为n的位的值置为0,为接受y中的相应字段做准备。
y << p+1-n //将y左移2位,这样y的最右4位的字段的开始位置将从第3位提前到第5位。
~tmp //00111100,从第p(5)位,长度为n(4)的位的值为1,其余值为0
y = (y << p+1-n) & ~tmp //将y的最右4位移到从第p(5)开始,长度为n(4)的位置处,
//并保持其中的值不变,而其他位置的值为0。
x | y //将y的最右4位的值赋给x中第5位开始,长度为4的位处,返回处理后的值。