[英]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. <<
逻辑上向左移动1
到end - 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 = 0
和1 & 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.