C++:掩码和解码位
C++: Mask and decoding bits
我刚刚遇到一个我不明白的功能,我想知道你是否可以给我解释一下。
unsigned long long x(unsigned long long value, int begin, int end)
{
unsigned long long mask = (1 << (end - begin)) - 1;
return (value >> begin) & mask;
}
谢谢
uksz
第一行将数字向左移动若干(结束 - 开始)位移位。
第二行向右移动了一些(右)位移位。
这样最后你将得到一个等于 "begin" 和 "end".
之间的位的掩码
函数的行为是未定义。应该是
unsigned long long mask = (1ULL << (end - begin)) - 1;
1
是一个 int
文字,并且应用比 int
中的位更多的左移是未定义的行为。 1ULL
是一个 unsigned long long 文字。
一旦这个问题得到解决,它将可靠地return范围内的 0 和 1 位开始结束,其他地方都是 0。
上述函数用作从数字中提取一系列位的掩码。它可以分为四个步骤。
第一步:
mask = 1UL << (end - begin)
<<
逻辑上将 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
将字符与掩码进行 AND 将导致提取移位数字的前 begin - end
位。这是因为 0 & x = 0
和 1 & x = x
.
正如 Bathsheba 在另一个答案中指出的那样,应该注意编写 1UL 以确保被移位的数字是 unsigned int
。否则将 int
移动更多位 int
是未定义的行为。 1UL 是一个 unsigned long long int
,值为 1
。
(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
我刚刚遇到一个我不明白的功能,我想知道你是否可以给我解释一下。
unsigned long long x(unsigned long long value, int begin, int end)
{
unsigned long long mask = (1 << (end - begin)) - 1;
return (value >> begin) & mask;
}
谢谢
uksz
第一行将数字向左移动若干(结束 - 开始)位移位。 第二行向右移动了一些(右)位移位。 这样最后你将得到一个等于 "begin" 和 "end".
之间的位的掩码函数的行为是未定义。应该是
unsigned long long mask = (1ULL << (end - begin)) - 1;
1
是一个 int
文字,并且应用比 int
中的位更多的左移是未定义的行为。 1ULL
是一个 unsigned long long 文字。
一旦这个问题得到解决,它将可靠地return范围内的 0 和 1 位开始结束,其他地方都是 0。
上述函数用作从数字中提取一系列位的掩码。它可以分为四个步骤。
第一步:
mask = 1UL << (end - begin)
<<
逻辑上将 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
将字符与掩码进行 AND 将导致提取移位数字的前 begin - end
位。这是因为 0 & x = 0
和 1 & x = x
.
正如 Bathsheba 在另一个答案中指出的那样,应该注意编写 1UL 以确保被移位的数字是 unsigned int
。否则将 int
移动更多位 int
是未定义的行为。 1UL 是一个 unsigned long long int
,值为 1
。
(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