【问题标题】:Trouble in understanding the bitwise operators left and right shift function in programming [duplicate]难以理解编程中的按位运算符左右移位功能[重复]
【发布时间】:2019-11-28 02:53:38
【问题描述】:

在 ANSI C 第 2.9 节中,按位运算符,我无法理解这个特定的代码。

我知道每个位运算符的工作原理,但组合需要一些帮助。

getbits(x, 4, 3)

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

【问题讨论】:

  • 如果你知道每个位运算符是如何工作的,我不明白你在问什么。
  • @Jabberwocky 我相信这与函数本身有关,我们不得不承认,除了名称之外再神秘不过了。

标签: c


【解决方案1】:

~0 是由二进制 1 组成的 int (111...111111)
~0&lt;&lt;n 在低位 (111...111000) 中引入 n 零。
~(~0&lt;&lt;n) 翻转位(000...000111)
x&gt;&gt;(p+1-n)x 移向低位 (00XXX...XXXXXX)。
&amp; 操作结合了前两个结果:高位零保持为零,低位 X 位(面向 1)保持原样 (00000...000XXX)。

因此,此函数从位 p 中检索 xn 位模式,但将 (p+1-n) 的位置移向低位(即放置在低位)。

【讨论】:

    【解决方案2】:

    该函数应该在位置p处提取宽度为n的位域。

    这个函数有问题:

    • p + 1 - n 似乎是假的,但如果p 是位域中最高有效位的位数,则它是位域右侧的位数,从0 开始编号为最低有效位有点..

    • 如果x 的最高有效位包含在位域中,则代码具有实现定义的行为,因为0 是有符号整数。应该改用0U

    • 代码无法提取全宽为unsigned int 的位域,因为移位大于或等于类型宽度的位数具有未定义的行为。移位应分为两部分,n - 1 位和额外的 1 位。 n - 1 将在 [0..31] 范围内,因此变量 shift 已完全定义。

    这是一个更便携的版本:

    // extract `n` bits at position `p`. n in [1..32], p in `[1..32]`
    unsigned getbits(unsigned x, int p, int n) {
       return (x >> (p + 1 - n)) & ~(~0U << (n - 1) << 1);
    }
    

    步骤如下:

    • 0U 是 unsigned int 空常量。
    • ~0U 已设置所有值位。
    • ~0 &lt;&lt; (n - 1) 的所有值位都已设置,但 n - 1 低位除外,这些位已被清除。
    • ~0 &lt;&lt; (n - 1) &lt;&lt; 1 的所有值位都已设置,但 n 低位除外,这些位已被清除。
    • ~(~0 &lt;&lt; (n - 1) &lt;&lt; 1) 设置了 n 低位。
    • p + 1 - n 是比位域低位的位数
    • x &gt;&gt; (p + 1 - n) 将值向右移动,将位域保留在低位位置。
    • (x &gt;&gt; (p + 1 - n)) &amp; ~(~0 &lt;&lt; (n - 1) &lt;&lt; 1) 屏蔽高阶位,只留下位域值。

    请注意,还有其他计算掩码的方法:

    ~0U >> (sizeof(unsigned) * CHAR_BIT - n)
    
    (1U << (n - 1) << 1) - 1
    

    【讨论】:

    • 您应该添加解释,将掩码的左移拆分为&lt;&lt; (n - 1)&lt;&lt; 1,而不是使用单个&lt;&lt; n,因为如果n 相等,这将是未定义的行为到unsigned 的宽度。我认为这并不明显。
    • p - 1 - n 至少需要p == 2(连同n == 1);较小的p 将导致负位移。原始版本在这方面似乎是正确的,考虑,考虑getbits(n, 0, 1)p 不是最不重要的,而是要使用的最重要的位。如果p 是最低有效位,我们可以移动p
    • 我同意0u,但我无法理解您对基于 1 的位编号的推理。据我了解,OP 的版本是基于 0 的。例如使用x=4+8+16p=4n=3,我们得到7,这对我来说似乎是正确的。
    • @Aconcagua:确实,我很愚蠢,我个人总是会指定位偏移,而不是最重要的位数。正如 prog-fh 所评论的那样,位数是基于 0 的。答案已修改。
    • 如果 K&R 错了,我会非常惊讶 ;^)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-11
    • 1970-01-01
    • 2015-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多