难以理解编程中的按位运算符左移和右移函数

  • 本文关键字:运算符 左移 函数 右移 编程 c
  • 更新时间 :
  • 英文 :


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

我知道每个按位运算符是如何工作的,但组合需要一些帮助。

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

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

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

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

此函数存在问题:

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

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

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

这是一个更便携的版本:

// 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是无符号的整数空常量。
  • ~0U设置了所有值位。
  • ~0 << (n - 1)设置了除n - 1低阶位之外的所有值位,这些位被清除。
  • ~0 << (n - 1) << 1设置了除n低阶位之外的所有值位,这些位被清除。
  • ~(~0 << (n - 1) << 1)设置了n低阶位。
  • p + 1 - n是比位域顺序低的位数
  • x >> (p + 1 - n)将值向右移动,将位域保留在低阶位位置。
  • (x >> (p + 1 - n)) & ~(~0 << (n - 1) << 1)屏蔽高阶位,只留下位域值。

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

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

最新更新