简体   繁体   English

C ++:掩码和解码位

[英]C++: Mask and decoding bits

I just came across a function I dont understand, and I was wondering if you could explain it to me. 我刚刚遇到了一个我不理解的功能,我想知道你是否可以向我解释一下。

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

Thanks 谢谢
uksz uksz

The above function serves as a mask to extract a range of bits from a number. 上述函数用作从数字中提取一系列位的掩码。 It can be broken down into four steps. 它可以分为四个步骤。

First step: 第一步:

mask = 1UL << (end - begin)

The << logically shifts 1 to the left by end - begin bits. <<逻辑上向左移动1end - begin位。 Since the binary of 1 is 000001 , a shift by 3 would correspond to 001000 . 由于1的二进制是000001 ,因此3的移位将对应于001000

Second step: 第二步:

mask = mask - 1

We have established from the previous step that mask at that point would be a sequence of zeroes, followed a one, followed by end - begin number of zeroes. 我们已经从前一步骤建立了那个掩码,那个掩码将是一个零序列,后跟一个,然后是end - begin的零数。 Subtracting 1 from such a number will result in the end - begin least significant bits being 1 , with everything else as 0 . 从这样的数字中减去1将导致end - begin最低有效位为1 ,其他一切为0 Subtracting 1 from our previous example yields 000111 . 从前一个示例中减去1得到000111

Third step: 第三步:

value >> begin

This will logically shift the target number (the one from which we need to extract bits) to the right by begin bits. 这将逻辑上将目标编号(我们需要从中提取位的编号)通过begin位向右移动。 Since we want the bits in the range begin to end , we can leave remove the bits before begin . 由于我们希望范围中的位begin to end ,我们可以在begin之前删除位。

Fourth step: 第四步:

(value >> begin) & mask

Taking the characterwise AND with the mask will result in the first begin - end bits of the shifted number being extracted. 采用字符AND与掩码将导致移位数的第一个begin - end位被提取。 This is because the 0 & x = 0 and 1 & x = x . 这是因为0 & x = 01 & x = x

As pointed out in the other answer by Bathsheba, care should be taken to write 1UL to ensure that the number being shifted is an unsigned int . 正如Bathsheba在另一个答案中指出的那样,应该注意写1UL以确保被移位的数字是unsigned int Else shifting an int by more bits in that int is undefined behavior. 别的换档的int由多个比特在于int是未定义的行为。 1UL is an unsigned long long int with the value 1 . 1UL是一个unsigned long long int ,值为1

The behaviour of the function is undefined . 该函数的行为未定义 It should be 它应该是

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

1 is an int literal and applying more left shifts than there are bits in that int is undefined behaviour. 1是一个int文字,并且应用了比有位更多的左移位,因为int是未定义的行为。 1ULL is an unsigned long long literal. 1ULL是一个unsigned long long literal。

Once this is fixed, it will reliably return just the 0 and 1 bits in the range begin to end, and 0 everywhere else. 一旦修复,它将可靠地返回范围开始结束的0和1位,以及其他地方的0。

The first line is shifting to the left the number by a number of (end - begin) bit shifts. 第一行向左移动了一些(结束 - 开始)位移。 The second line is shifting to the right by a number of (right) bit shifts. 第二行通过多个(右)位移位向右移动。 This way at the end you will have a mask that is equal to the bits between "begin" and "end". 这样,最后你将有一个等于“begin”和“end”之间位的掩码。

(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 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM