我刚刚遇到了一个我不了解的功能,我想知道您能否向我解释一下。
unsigned long long x(unsigned long long value, int begin, int end)
{
unsigned long long mask = (1 << (end - begin)) - 1;
return (value >> begin) & mask;
}
Run Code Online (Sandbox Code Playgroud)
谢谢
uksz
函数的行为是undefined。它应该是
unsigned long long mask = (1ULL << (end - begin)) - 1;
1是一个int文字并且应用比其中的位更多的左移int是未定义的行为。1ULL是一个 unsigned long long 字面量。
一旦修复,它将可靠地只返回范围开始到结束的 0 和 1 位,其他地方都返回 0。
上述功能用作从数字中提取位范围的掩码。它可以分为四个步骤。
第一步:
mask = 1UL << (end - begin)
Run Code Online (Sandbox Code Playgroud)
的<<逻辑移位1到左边由end - begin比特。由于1is 的二进制,因此000001移位3将对应于001000。
第二步:
mask = mask - 1
Run Code Online (Sandbox Code Playgroud)
从上一步开始,我们已经确定,此时的掩码将是一个零序列,然后是一个零,然后是end - begin零个数。减去1该数字将导致end - begin最低有效位为1,其他所有内容均为0。1从我们前面的示例中减去,将得出结果000111。
第三步:
value >> begin
Run Code Online (Sandbox Code Playgroud)
这将在逻辑上将目标编号(我们需要从中提取位的数字)向右移一位begin。由于我们希望这些位在范围内begin to end,因此我们可以在删除之前删除这些位begin。
第四步:
(value >> begin) & mask
Run Code Online (Sandbox Code Playgroud)
对掩码进行按字符与运算将导致begin - end提取移位数的第一位。这是因为0 & x = 0和1 & x = x。
正如Bathsheba在另一个答案中所指出的那样,应注意写1UL以确保要移位的数字是unsigned int。否则,将an移动int更多位int是未定义的行为。1UL是unsigned long long int带值的1。