如何在C中创建最小有效位设置为1的掩码

有人可以向我解释这个function吗?

具有最低有效n位的掩码设置为1。

例如:

n = 6 – > 0x2F,n = 17 – > 0x1FFFF //我根本得不到这些,尤其是n = 6 – > 0x2F

还有什么是面具?

通常的方法是取1 ,然后将其向左移位n位。 这将给你类似的东西: 00100000 。 然后从中减去一个,这将清除所设置的位,并设置所有不太重要的位,因此在这种情况下,我们得到: 00011111

掩码通常用于按位操作,特别是and 。 您可以使用上面的掩码自行获取5个最低有效位,与可能存在的任何其他位置隔离。 这在处理通常具有单个硬件寄存器的硬件时尤其常见,该硬件寄存器包含表示多个完全独立的,不相关的量和/或标志的位。

对于正确性和性能,实现这一目标的最佳方法已经改变,因为在2012年由于现代x86处理器(特别是BLSMSK)中BMI指令的出现而回答了这个问题。

这是解决此问题的好方法,同时保留与旧处理器的向后兼容性。

此方法是正确的,而当前的顶部答案在边缘情况下产生未定义的行为。

当允许使用BMI指令进行优化时,Clang和GCC会将gen_mask()压缩为两个操作。 使用支持硬件时,请务必为BMI指令添加编译器标志: -mbmi -mbmi2

 #include  #include  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; } 

掩码是整数值的常用术语,该整数值与另一个整数值进行逐位AND运算,OR运算,XOR运算等。

例如,如果要提取int变量的8个最低有效位,则执行variable & 0xFF 。 0xFF是一个掩码。

同样,如果要设置位0和8,则执行variable | 0x101 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 ++中)中,您不能合法地将变量左移与变量所具有的位数一样多,因此如果整数是32位,则1<<32导致undefined behavior 。 还应避免使用有符号整数溢出,因此应使用无符号值,例如1u << 31

我相信你的第一个例子应该是0x3f

0x3f是数字63hex表示法,它是二进制的111111 ,因此最后6位(最低有效6位)设置为1

以下小C程序将计算正确的掩码:

 #include  #include  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与某个值n组合,则结果将在除6个最低有效位之外的所有位中具有零,并且这6位将从值n更改地复制。

& mask的情况下,掩码中的二进制0表示“无条件地将结果位设置为0”, 1表示“将结果位设置为输入值位”。 对于| 掩码,掩码中的0将结果位设置为输入位, 1无条件地将结果位设置为1 ,对于^掩码, 0将结果位设置为输入位, 1将结果位设置为输入位的补码。