有人可以向我解释一下这个功能吗?
最低有效 n 位设置为 1 的掩码。
前任:
n = 6 --> 0x2F, n = 17 --> 0x1FFFF // 我一点也不明白,尤其是 n = 6 --> 0x2F
还有,什么是口罩?
有人可以向我解释一下这个功能吗?
最低有效 n 位设置为 1 的掩码。
前任:
n = 6 --> 0x2F, n = 17 --> 0x1FFFF // 我一点也不明白,尤其是 n = 6 --> 0x2F
还有,什么是口罩?
通常的方法是取 a 1
,并将其向左移动n
。这会给你类似的东西:00100000
. 然后从中减去一个,这将清除已设置的位,并设置所有次要有效位,因此在这种情况下,我们将得到:00011111
。
掩码通常用于按位运算,尤其是and
. 您将使用上面的掩码自己获取 5 个最低有效位,与可能存在的任何其他内容隔离。这在处理通常具有单个硬件寄存器的硬件时尤其常见,该寄存器包含表示许多完全独立的、不相关的数量和/或标志的位。
掩码是一个整数值的常用术语,它与另一个整数值按位与、或、异或等。
例如,如果您想提取一个 int 变量的 8 个最低有效数字,您可以使用variable & 0xFF
. 0xFF 是一个掩码。
同样,如果您想设置位 0 和 8,您可以这样做variable | 0x101
,其中 0x101 是掩码。
或者,如果您想反转相同的位,您可以这样做variable ^ 0x101
,其中 0x101 是掩码。
要为您的情况生成一个掩码,您应该利用一个简单的数学事实,即如果您将 1 添加到您的掩码(掩码的所有最低有效位都设置为 1,其余位设置为 0),您将获得一个值为2.
所以,如果你生成最接近的 2 的幂,那么你可以从中减去 1 来得到掩码。
使用 C中的左移<<
运算符很容易生成 2 的正幂。
因此,1 << n
产生 2 n。在二进制中,它是 10...0 和n
0。
(1 << n) - 1
将产生一个n
最低位设置为 1 的掩码。
现在,您需要注意左移时的溢出。在 C(和 C++)中,您不能合法地将变量左移尽可能多的位位置,因此如果 int 是 32 位,则1<<32
结果为undefined behavior
. 还应避免有符号整数溢出,因此应使用无符号值,例如1u << 31
.
由于现代 x86 处理器(特别是 BLSMSK)中 BMI 指令的出现,自 2012 年问及这个问题以来,实现这一点的最佳方法已经改变。
这是解决此问题的好方法,同时保持与旧处理器的向后兼容性。
这种方法是正确的,而当前的最佳答案在极端情况下会产生未定义的行为。
当允许使用 BMI 指令进行优化时,Clang 和 GCC 会将 gen_mask() 压缩为两个操作。使用支持硬件,请务必为 BMI 指令添加编译器标志:
-mbmi -mbmi2
#include <inttypes.h>
#include <stdio.h>
uint64_t gen_mask(const uint_fast8_t msb) {
const uint64_t src = (uint64_t)1 << msb;
return (src - 1) ^ src;
}
int main() {
uint_fast8_t msb;
for (msb = 0; msb < 64; ++msb) {
printf("%016" PRIx64 "\n", gen_mask(msb));
}
return 0;
}
首先,对于那些只想要代码来创建面具的人:
uint64_t bits = 6;
uint64_t mask = ((uint64_t)1 << bits) - 1;
# Results in 0b111111 (or 0x03F)
对于那些想知道面具是什么的人:
掩码通常是值的名称,我们使用它来使用按位运算(如 AND、OR、XOR 等)来操作其他值。
短掩码通常以二进制表示,我们可以明确地看到所有设置为 1 的位。
较长的掩码通常以十六进制表示,一旦掌握它就很容易阅读。
您可以在此处阅读有关 C 中的按位运算的更多信息,以便更好地掌握材料。
我相信你的第一个例子应该是0x3f
.
0x3f
63
是二进制数字的十六进制表示法111111
,因此最后 6 位(最低有效 6 位)设置为1
.
下面的小 C 程序将计算正确的掩码:
#include <stdarg.h>
#include <stdio.h>
int mask_for_n_bits(int n)
{
int mask = 0;
for (int i = 0; i < n; ++i)
mask |= 1 << i;
return mask;
}
int main (int argc, char const *argv[])
{
printf("6: 0x%x\n17: 0x%x\n", mask_for_n_bits(6), mask_for_n_bits(17));
return 0;
}
0x2F
是0010 1111
二进制的 - 这应该是0x3f
,它是0011 1111
二进制的并且设置了 6 个最低有效位。
同样,0x1FFFF
是0001 1111 1111 1111 1111
二进制的,它设置了 17 个最低有效位。
“掩码”是一个值,它旨在使用按位运算符(如 )与另一个值组合&
,|
或者^
单独设置、取消设置、翻转或保持其他值中的位不变。
例如,如果您使用运算符将掩码0x2F
与某个值组合,则结果将在除 6 个最低有效位之外的所有位中都为零,并且这 6 个位将从 value 中原样复制。n
&
n
在掩码的情况下,&
掩码中的二进制0
表示“无条件地将结果位设置为 0”,a1
表示“将结果位设置为输入值位”。对于|
掩码,掩码中的 an0
将结果位设置为输入位,a1
无条件地将结果位设置为1
,对于^
掩码,0
将结果位设置为输入位,a1
将结果位设置为输入位。