将x中从第p位开始的n个(二进制)位设置为y中最右边n位的值,x的其余各位保持不变...

     源自《The C Programming Language》P40 pr2-6:

   编写一个函数setbits(x, p, n, y),该函数返回对x执行下列操作后的结果值:将x中从第p位开始的n个(二进制)位设置为

     y中最右边n位的值,x的其余各位保持不变。

   代码:  

ContractedBlock.gif ExpandedBlockStart.gif main.c
 
    
1 #include < stdio.h >
2
3 unsigned setbits(unsigned x, int p, int n, unsigned y);
4
5 int main()
6 {
7
8 unsigned num = 125 ; // 待处理的十进制数
9 int pos = 7 ;   // 从数1的第pos位开始(从右至左)
10 int cnt = 4 ;   // 处理字段的长度
11 unsigned numset = 65 ;   // 被获取某个字段的十进制数
12
13 printf( " %u\n " , setbits(num, pos, cnt, numset));
14
15 return 0 ;
16 }
17
18 /* *******************************************************
19 **函数名称:setbits
20 ** 功能:将x中从第p位开始的n个位设置成y中最右边n位的值,
21 ** x的其余各位保持不变
22 ** 参数:x:待处理的数
23 ** p:从y中获取的字段放入x中的开始位置
24 ** n:从y中获取的字段的长度
25 ** y:被获取字段的数
26 ** 返回值:x中第p位开始长度为n的二进制位被替代成y的最右n
27 ** 个字段的值,其他位保持不变,然后返回这个结果。
28 * */
29
30 unsigned setbits(unsigned x, int p, int n, unsigned y)
31 {
32 unsigned tmp;
33
34 tmp = ( ~ 0 << p + 1 ) | ~ ( ~ 0 << p + 1 - n); // tmp:从第p位开始,长度为n,其中位值为0,其余
35   // 位值为1的二进制数--此处用十进制数来表示。
36 x = x & tmp; // 将x中的第p位开始长度为n的位值置为0,其余不变。
37 y = (y << p + 1 - n) & ~ tmp; // 将y左移p+1-n位,然后与~tmp相与,这样y的从第p
38 // 位开始,长度为n的位的值即为操作前的y的最右n位
39 // 的值,而此时y的其余位的值为0。
40 return x | y; // 将操作后的x,y相与,即实现功能。
41
42 }

  分析:

  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的位处,返回处理后的值。

转载于:https://www.cnblogs.com/roma823/archive/2011/05/04/2101255.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值