取一个数从右边第 p 位开始向右数 n 位的字段理解

《C 程序设计语言》p39 底部 getbits 函数代码理解

/* getbits函数:返回x中从第p位开始的n位 */
unsigned getbits(unsigned x, int p, int n)
{
	return (x >> (p+1-n)) & ~(~0 << n);
}

在这段函数中,x 为无符号整型操作数,可以通过举例子来理解函数中的位运算为什么拿到了第 p 位开始的 n 位。

假设 x 为 40, 即 0010 1000 我们要取第 4 位开始的 3 位,即 getbits(40, 4, 3)

直接看,我们很快就能知道要取的就是从右边数第 4 位后的三个 即 010

首先地一个操作 x >> (p+1-n) 的目的就是为了让那三位顶到最右边,这里 p + 1是因为这里假定最右边的第一位是第 0 位,这样向右位移的两位就是 0000 1010 那么之后我们又如何知道要得就是这三位呢? 前提就是让这三位左边的数都为 0 即可,这时就可以想到另外一个为运算符 & 按位与

按位与只有在两个数都为 1 的时候才会是 1,所以我们只需要有这样一个二进制数 0000 0111 就可以让右三位该是几就是几,而其他的必定是 0。也就是说我们只需要写一个能得到这个二进制数的表达式即可,便是上述代码中的 ~(~0 << n)

首先让 0 都变成 1 ~0 => 1111 1111 随后向左位移要取的位数,低位补 0 ~0 << 3 => 1111 1000 然后再进行一次取反就得到了0000 0111

接下来只需要跟之前顶到最右的那三位进行按位与操作就能让 0000 1010 => 0000 0010 这样就拿到了 x 中从第 4 位开始的 3 位