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

时间:2012-09-14 00:29:50

标签: c bit-manipulation bitmask

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

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

例如:

n = 6 - > 0x2F,n = 17 - > 0x1FFFF //我根本得不到这些,特别是n = 6 - >值为0x2F

另外,什么是面具?

6 个答案:

答案 0 :(得分:24)

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

掩码通常用于按位操作,尤其是and。您可以使用上面的掩码自行获取5个最低有效位,与可能存在的任何其他位置隔离。这在处理硬件时尤为常见,这些硬件通常只有一个硬件寄存器,其中包含代表一些完全独立的无关数量和/或标志的位。

答案 1 :(得分:8)

对于正确性和性能,自2012年因为现代x86处

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

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

当允许使用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;
}

答案 2 :(得分:7)

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

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

答案 3 :(得分:0)

我相信你的第一个例子应该是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;
}

答案 4 :(得分:0)

0x2F是二进制的0010 1111 - 这应该是0x3f,二进制是0011 1111,并且设置了6个最低有效位。

同样,0x1FFFF为二进制0001 1111 1111 1111 1111,其中设置了17个最低有效位。

“掩码”是一个值,旨在使用&|^之类的按位运算符与其他值组合,以单独设置,取消设置,翻转或离开未改变其他值中的位。

例如,如果使用0x2F运算符将掩码n与某个值&组合在一起,则除了6个最低有效位之外,结果中的所有值都为零,并且位将从值n中保持不变。

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

答案 5 :(得分:0)

首先,对于只希望代码创建掩码的用户:

uint64_t bits = 6;
uint64_t mask = ((uint64_t)1 << bits) - 1;
# Results in 0b111111 (or 0x03F)

对于那些想知道什么是面具的人:

掩码通常是值的名称,我们使用它使用AND,OR,XOR等按位运算来操纵其他值。

短掩码通常以二进制表示,我们可以在其中明确看到设置为1的所有位。

更长的掩码通常以十六进制表示,一旦掌握它,它真的很容易阅读。

您可以阅读有关C here中按位运算的更多信息,从而可以更好地掌握本文的内容。