1.将x执行以下操作
第p位开始的n(二进制)个位,设置为y中最右边的n位,x的其余位不变
x: xxxm mxxx
y: yyyy yynn
思路:将x中的m变为0,将y中的y变为0,再左移至相应位置,然后再 与 。
x: xxx0 0xxx
y: 0000 00nn
x: xxx0 0xxx
y: 000n n000
x: xxxn nxxx
unsigned setbits(unsigned x, int p, int n, unsigned y){
return x & ~(~(~0 << n) << (p+1-n)) | (y & ~(~0 << n)) << (p+1-n);
}
~0 << n//把全1的屏蔽码左移n位,右边出现n个0
~(~0 << n)//取反,右边出现n个1,其余位为0
~(~0 << n) << (p+1-n)//把屏蔽码右边的n个1左移至对应位置
~(~(~0 << n) << (p+1-n))//再取反
x & ~(~(~0 << n) << (p+1-n))//用屏蔽码和x进行与操作
~(~0 << n)//右边n位为1,其余为0
y & ~(~0 << n)//与y相与,将y的无关位置0
y & ~(~0 << n) << (p+1-n)//把y左移至对应位置
x & ~(~(~0 << n) << (p+1-n)) | y & ~(~0 << n) << (p+1-n)//或,得到结果
设p=4,n=2
x屏蔽码:
1111 1111
1111 1100
0000 0011
0001 1000
1110 0111
x:
xxxm mxxx
xxx0 0xxx
y屏蔽码:
1111 1111
1111 1100
0000 0011
y:
yyyy yynn
0000 00nn
000n n000
最终x: xxxn nxxx
2.将x执行以下操作
第p位开始的n(二进制)个位,取反,x的其余位不变
x: xxxn nxxx
xxx~n ~nxxx
思路:还是用屏蔽码与x进行异或(^)
unsigned invert(unsigned x, int p, int n){
return x ^ (~(~0 << n) << (p+1-n));
}
可以借鉴上面的思路分析
~0 << n//把全1的屏蔽码左移n位,右边出现n个0
~(~0 << n)//取反,右边出现n个1,其余位为0
~(~0 << n) << (p+1-n)//把屏蔽码右边的n个1左移至对应位置
x ^ (~(~0 << n) << (p+1-n))//用屏蔽码和x进行异或操作
3.将x执行以下操作
将x循环右移n位(最右边移出的值将从最左端移入)
此处为真循环
//将x循环右移n位(最右边移出的值将从最左端移入)
unsigned rightrot(unsigned x, int n){
int wordlength(void);
int rbit;
while(n-- >0){
rbit = (x & 1) << (wordlength() - 1);
x = x >> 1;
x = x | rbit;
}
return x;
}
//计算运行程序的计算机所使用的的字长
int wordlength(void){
int i;
unsigned v = (unsigned) ~0;
for(i = 1;(v = v >> 1) > 0;i++)
;
return i;
}
用rebit将x最右端移到最左端位置(wordlength() - 1),然后将x右移一位,再与rebit进行或操作。即完成一次右移,如此循环n次。
假循环,就是将右端n位全部移到左端。