【问题标题】:C++: Mask and decoding bitsC++:掩码和解码位
【发布时间】:2016-02-20 07:12:43
【问题描述】:

我刚刚遇到一个我不明白的函数,我想知道你是否可以给我解释一下。

unsigned long long x(unsigned long long value, int begin, int end)
{
    unsigned long long mask = (1 << (end - begin)) - 1;
    return (value >> begin) & mask;
}

谢谢
英国

【问题讨论】:

  • 也许你应该举个例子,例如value = 1100111000110010begin = 3end = 7,然后手工解决……

标签: c++ mask masking


【解决方案1】:

上述函数用作从数字中提取一系列位的掩码。它可以分为四个步骤。

第一步:

mask = 1UL << (end - begin)

&lt;&lt; 在逻辑上将1 向左移动end - begin 位。由于1 的二进制是000001,因此移位3 对应于001000

第二步:

mask = mask - 1

我们从上一步中确定,此时的掩码将是一系列零,然后是一个,然后是 end - begin 零个数。从这样的数字中减去1 将导致end - begin 的最低有效位为1,其他所有位为0。从我们之前的示例中减去1 得到000111

第三步:

value >> begin

这将在逻辑上将目标数字(我们需要从中提取位的数字)向右移动begin 位。由于我们想要begin to end 范围内的位,我们可以保留删除begin 之前的位。

第四步:

(value >> begin) & mask

对掩码进行字符与运算将导致提取移位数字的前begin - end 位。这是因为0 &amp; x = 01 &amp; x = x

正如 Bathsheba 在另一个答案中指出的那样,应注意写入 1UL 以确保要移动的数字是unsigned int。否则将int 移动更多位,因为int 是未定义的行为。 1UL 是一个unsigned long long int,其值为1

【讨论】:

  • 否则编译器可能会吃掉你的猫。如果您提到UB,那么这个答案将很难更好。 (我完全不介意你把我的答案的重点放在这里)。
  • @Bathsheba :提到 UB,当然有适当的信用。
  • 顺便说一下要1ULL。
  • 这就是未定义行为的本质。您必须使用 1ULL 来保证其正常工作。
【解决方案2】:

函数的行为是未定义。应该是

unsigned long long mask = (1ULL &lt;&lt; (end - begin)) - 1;

1 是一个int 文字,并且应用比int 未定义的行为更多的位。 1ULL 是一个 unsigned long long 字面量。

一旦修复此问题,它将可靠地仅返回范围中的 0 和 1 位开始到结束,并在其他任何地方返回 0。

【讨论】:

  • 嗯。如果定义了0ULL - 1,您是否知道?如果end == sizeof(unsigned long long)begin == 0,我们就这样结束了。
  • 0ULL - 1 等于 std::numeric_limits(unsigned long long)::max()。该标准坚持对无符号类型进行环绕。
【解决方案3】:

第一行将数字向左移动了一些(结束 - 开始)位移。 第二行向右移动了一些(右)位移位。 这样,最后您将获得一个掩码,该掩码等于“开始”和“结束”之间的位。

【讨论】:

    【解决方案4】:
    (1) 1 in the expression implies 32 bit number on 32 bit machines.  
    So we need uul after 1 to make it 64 bit. Will work for MOST of the              
    cases.          
    unsigned long long mask = (1ull << (end - begin)) - 1;  
    
    (2) When begin=0, end=63, we will still see the wrong mask in case#1  
    The mask will come out be 0x7FFFFFFFFFFFFFFF  
    The following will fix that problem as well.  
    unsigned long long mask = ((1ull << end) - (1ull << begin)) | (1ull << end);
    
    This will generate the mask 0xFFFFFFFFFFFFFFFF 
    

    【讨论】:

      猜你喜欢
      • 2010-09-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多