需要帮助理解K&R C第2章中的"getbits()"方法

Joh*_*udy 28 c bit-manipulation operators bit-shift complement

在第2章,关于按位运算符的部分(第2.9节),我无法理解其中一个示例方法是如何工作的.

这是提供的方法:

unsigned int getbits(unsigned int x, int p, int n) {
    return (x >> (p + 1 - n)) & ~(~0 << n);
}
Run Code Online (Sandbox Code Playgroud)

这个想法是,对于给定的数字x,它将返回从位置p开始的n位,从右边开始计数(最右边的位是位置0).给出以下方法:main()

int main(void) {
    int x = 0xF994, p = 4, n = 3;
    int z = getbits(x, p, n);
    printf("getbits(%u (%x), %d, %d) = %u (%X)\n", x, x, p, n, z, z);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出是:

getbits(63892 (f994), 4, 3) = 5 (5)

我得到了部分内容,但我对"大局"感到困扰,主要是因为我不理解的比特(没有双关语).

我特别遇到问题的部分是补充部分:~(~0 << n).我想我得到了第一部分,处理x ; 这是我正在努力的这部分(然后是面具) - 以及如何将它们组合在一起以实际检索这些位.(我已经验证了它正在使用代码并使用calc.exe检查我的结果 - 感谢上帝它有一个二进制视图!)

有帮助吗?

pax*_*blo 38

我们的例子中使用16位.在那种情况下,~0等于

1111111111111111
Run Code Online (Sandbox Code Playgroud)

当我们左移这些n位(在你的情况下为3)时,我们得到:

1111111111111000
Run Code Online (Sandbox Code Playgroud)

因为1左边的s被丢弃了,0s被输入了右边.然后重新补充它给出:

0000000000000111
Run Code Online (Sandbox Code Playgroud)

所以这只是一个聪明的方法,n在数字的最不重要部分得到1位.

您描述的"x位"已将给定数字(f994)向右移动得足够远,以便最不重要的3位是您想要的位数.在此示例中,您请求的位被"."包围.字符.

ff94             11111111100.101.00  # original number
>> p+1-n     [2] 0011111111100.101.  # shift desired bits to right
& ~(~0 << n) [7] 0000000000000.101.  # clear all the other (left) bits
Run Code Online (Sandbox Code Playgroud)

你有你的位.塔达!!


Non*_*one 11

我想说最好的办法是手工解决问题,这样你就会明白它是如何运作的.

这是我使用8位unsigned int所做的.

  1. 我们的数字是75,我们想要从位置6开始的4位.函数的调用将是getbits(75,6,4);

  2. 二进制75是0100 1011

  3. 因此,我们创建一个4位长的掩码,从最低位开始,这样做.

~0 = 1111 1111
<< 4 = 1111 0000
~ = 0000 1111

好的,我们拿到了面具.

  1. 现在,我们将我们想要的数字从数字中推出到最低位,因此我们将二进制75移位6 + 1-4 = 3.

0100 1011 >> 3 0000 1001

现在我们有一个低位正确位数的掩码和我们想要的低位原始数字的位.

  1. 所以我们和他们
  0000 1001 
& 0000 1111 ============ 0000 1001

所以答案是十进制9.

注:高阶四位恰好是全零,使得屏蔽冗余在这种情况下,但它可能是任何东西,这取决于我们开始与数字的值.


Dav*_*ant 6

~(~0 << n)创建一个将n打开最右边位的掩码.

0
   0000000000000000
~0
   1111111111111111
~0 << 4
   1111111111110000
~(~0 << 4)
   0000000000001111
Run Code Online (Sandbox Code Playgroud)

用其他东西对结果进行AND运算将返回那些n位中的内容.

编辑:我想指出这个程序员的计算器我一直在使用:AnalogX PCalc.