“需要帮助理解”;getbits();K&;R C

“需要帮助理解”;getbits();K&;R C,c,operators,bit-manipulation,bit-shift,complement,C,Operators,Bit Manipulation,Bit Shift,Complement,在第2章,关于位运算符的部分(第2.9节),我很难理解其中一个示例方法是如何工作的 以下是提供的方法: unsigned int getbits(unsigned int x, int p, int n) { return (x >> (p + 1 - n)) & ~(~0 << n); } 输出为: getbits(63892(f994),4,3)=5(5) 我得到了其中的一部分,但在“大局”方面遇到了麻烦,主要是因为我不明白其中的一些细节(并非双关语

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

以下是提供的方法:

unsigned int getbits(unsigned int x, int p, int n) {
    return (x >> (p + 1 - n)) & ~(~0 << n);
}
输出为:

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

我得到了其中的一部分,但在“大局”方面遇到了麻烦,主要是因为我不明白其中的一些细节(并非双关语)


我特别关注的是补码部分:
~(~0让我们使用16位作为示例。在这种情况下,
~0
等于

1111111111111111
当我们左移此
n
位(在您的情况下为3位)时,我们得到:

因为左侧的
1
s被丢弃,右侧的
0
s被输入。然后对其进行重新补充,得到:

0000000000000111
因此,这是一种聪明的方法,可以在数字的最低有效部分获得
n
1位

您描述的“x位”已将给定的数字(
f994=1111 1001 1001 0100
)向右移动足够远,以便最低有效的3位是您想要的。在本例中,您请求的输入位在那里,所有其他输入位都标记为
,因为它们对最终结果不重要:

ff94             ...........101..  # original number
>> p+1-n     [2] .............101  # shift desired bits to right
& ~(~0 << n) [7] 0000000000000101  # clear all the other (left) bits
ff94……….101.#原始编号
>>p+1-n[2]……101#将所需位右移
&~0使用以下示例:
INTX=0xF994,p=4,n=3;
intz=getbits(x,p,n)

并将重点放在这一系列操作上
(~0
~)我认为最好的办法是手工解决问题,这样你就会明白它是如何工作的

下面是我使用8位无符号整数所做的

  • 我们的数字是75,我们想要从位置6开始的4位。 函数的调用是getbits(75,6,4)

  • 二进制中的75是0100 1011

  • 因此,我们创建一个4位长的掩码,从最低阶位开始,就是这样做的

  • ~0=1111111
    300001001

    现在我们有了一个低阶正确位数的掩码,以及我们想要的低阶原始位数的位数

  • 所以我们&他们
  • 0000 1001
    & 0000 1111 ============ 0000 1001 所以答案是十进制9


    注意:高阶半字节恰好是全零,这使得掩蔽在本例中是多余的,但它可能是任何东西,这取决于我们开始使用的数字的值。

    还没有人提到它,但在ANSI C
    ~0中,在
    ANSI C~0>>中,n
    会导致未定义的行为

    //关于左移导致问题的帖子是错误的

    无符号字符m,l

    m=~0>>4;产生255,并且等于~0,但是

    m=~0; l=m>>4;产生的正确值15与:

    m=255>>4


    左移负数
    ~0@jim:嘿,这不会影响你文章的准确性。内容方面比其他两种方式都要复杂,最好使用代码块和对齐更改。文章使用wiki标记,并在“?”上添加一个tute页面链接答案框上方。我必须读两遍才能检查它。我本打算建议右移,以保存指令,但我猜,
    ~(~0我不懂什么,哪里错了?int a=0;所以printf(“%d”,a)给出0。现在,a=~a所以printf(“%d”,a)给出-1,为什么?@Anatoly:这是因为
    ~
    将所有位反转为1,在两个补码编码中,这是-1。回答得很好。我终于理解了这个例子!:)
    0000000000000111
    
    ff94             ...........101..  # original number
    >> p+1-n     [2] .............101  # shift desired bits to right
    & ~(~0 << n) [7] 0000000000000101  # clear all the other (left) bits
    
    0
       0000000000000000
    ~0
       1111111111111111
    ~0 << 4
       1111111111110000
    ~(~0 << 4)
       0000000000001111
    
    0000 1001
    & 0000 1111 ============ 0000 1001