有人可以向我解释这个功能吗?
具有最低有效n位的掩码设置为1。
例如:
n = 6 - > 0x2F,n = 17 - > 0x1FFFF //我根本得不到这些,尤其是n = 6 - > 0x2F
还有什么是面具?
通常的方法是采取1
,并将其左移n
位。这会给你一些像:00100000
。然后从中减去一个,这将清除设置的位,并设置所有不太重要的位,所以在这种情况下我们得到:00011111
。
掩码通常用于按位操作,尤其是and
。您可以使用上面的掩码自行获取5个最低有效位,与可能存在的任何其他位置隔离。这在处理通常具有单个硬件寄存器的硬件时尤其常见,该硬件寄存器包含表示多个完全独立的,不相关的量和/或标志的位。
掩码是整数值的常用术语,该整数值与另一个整数值进行逐位AND运算,OR运算,XOR运算等。
例如,如果要提取int变量的8个最低有效数字,则执行variable & 0xFF
。 0xFF是一个掩码。
同样,如果要设置位0和8,则执行variable | 0x101
,其中0x101是掩码。
或者,如果要反转相同的位,则执行variable ^ 0x101
,其中0x101是掩码。
要为你的情况生成一个掩码,你应该利用一个简单的数学事实:如果你在掩码中添加1(掩码的所有最低有效位设置为1,其余的为0),你得到的值就是2。
因此,如果您生成最接近2的幂,则可以从中减去1以获得掩码。
使用C中的左移<<
算子很容易生成2的正幂。
因此,1 << n
产生2n。在二进制中,它是10 ... 0与n
0s。
(1 << n) - 1
将生成一个n
最低位设置为1的掩码。
现在,您需要注意左移的溢出。在C(和C ++中),你不能合法地将变量左移由变量所具有的位数,因此如果整数是32位,则1<<32
会导致undefined behavior
。还应避免使用有符号整数溢出,因此应使用无符号值,例如: 1u << 31
。
对于正确性和性能,实现这一目标的最佳方法已经改变,因为在2012年由于现代x86处理器(特别是BLSMSK)中BMI指令的出现而回答了这个问题。
这是解决此问题的好方法,同时保留与旧处理器的向后兼容性。
此方法是正确的,而当前的顶部答案在边缘情况下产生未定义的行为。
当允许使用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;
}
我相信你的第一个例子应该是0x3f
。
0x3f
是数字63
的十六进制表示法,111111
是二进制的1
,因此最后6位(最低有效6位)设置为#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;
}
。
以下小C程序将计算正确的掩码:
0x2F
0010 1111
是二进制的0x3f
- 这应该是0011 1111
,它是二进制的0x1FFFF
,并且设置了6个最低有效位。
类似地,0001 1111 1111 1111 1111
是二进制的&
,它具有17个最低有效位。
“掩码”是一个值,旨在使用像|
,^
或0x2F
这样的按位运算符与另一个值组合,以单独设置,取消设置,翻转或保持其他值中的位不变。
例如,如果使用n
运算符将掩码&
与某个值n
组合,则结果将在除6个最低有效位之外的所有位中具有零,并且这些6位将从值&
未更改地复制。
在0
掩码的情况下,掩码中的二进制1
意味着“无条件地将结果位设置为0”,而|
意味着“将结果位设置为输入值位”。对于0
掩码,掩码中的1
将结果位设置为输入位,1
无条件地将结果位设置为^
,对于0
掩码,1
将结果位设置为输入位,uint64_t bits = 6;
uint64_t mask = ((uint64_t)1 << bits) - 1;
# Results in 0b111111 (or 0x03F)
设置结果位到输入位的补码。
首先,对于那些只想要代码来创建掩码的人:
here
对于那些想知道面具是什么的人:
掩码通常是值的名称,我们使用它来使用按位运算(如AND,OR,XOR等)来操纵其他值。
短掩码通常以二进制表示,我们可以在其中明确地看到所有设置为1的位。
较长的掩码通常以十六进制表示,一旦掌握它就很容易阅读。
您可以在C qazxswpoi中阅读有关按位操作的更多信息,以便更好地掌握材料。