如何使用位掩码?

时间:2013-09-03 12:04:40

标签: c++ c++11 bitmask

我如何在C ++中使用它? 何时使用有用?
请给我一个使用位掩码的问题示例,它实际上是如何工作的。 谢谢!

4 个答案:

答案 0 :(得分:101)

简单地说,位掩码有助于操纵多个值的位置。这里有一个很好的例子;

Bitflags是一种在一个变量中存储多个不相互排斥的值的方法。你以前可能已经看过了。每个标志都是一个位置,可以设置为开或关。然后,每个位位置都有一堆位掩码#defined,以便您可以轻松操作它:

    #define LOG_ERRORS            1  // 2^0, bit 0
    #define LOG_WARNINGS          2  // 2^1, bit 1
    #define LOG_NOTICES           4  // 2^2, bit 2
    #define LOG_INCOMING          8  // 2^3, bit 3
    #define LOG_OUTGOING         16  // 2^4, bit 4
    #define LOG_LOOPBACK         32  // and so on...

// Only 6 flags/bits used, so a char is fine
unsigned char flags;

// initialising the flags
// note that assigning a value will clobber any other flags, so you
// should generally only use the = operator when initialising vars.
flags = LOG_ERRORS;
// sets to 1 i.e. bit 0

//initialising to multiple values with OR (|)
flags = LOG_ERRORS | LOG_WARNINGS | LOG_INCOMING;
// sets to 1 + 2 + 8 i.e. bits 0, 1 and 3

// setting one flag on, leaving the rest untouched
// OR bitmask with the current value
flags |= LOG_INCOMING;

// testing for a flag
// AND with the bitmask before testing with ==
if ((flags & LOG_WARNINGS) == LOG_WARNINGS)
   ...

// testing for multiple flags
// as above, OR the bitmasks
if ((flags & (LOG_INCOMING | LOG_OUTGOING))
         == (LOG_INCOMING | LOG_OUTGOING))
   ...

// removing a flag, leaving the rest untouched
// AND with the inverse (NOT) of the bitmask
flags &= ~LOG_OUTGOING;

// toggling a flag, leaving the rest untouched
flags ^= LOG_LOOPBACK;



**
  

警告:不要使用相等运算符(即bitflags == bitmask)   用于测试是否设置了标志 - 该表达式仅在以下情况下才为真   该标志已设置,所有其他标志未设置。测试单个标志   你需要使用&和==:

**

if (flags == LOG_WARNINGS) //DON'T DO THIS
   ...
if ((flags & LOG_WARNINGS) == LOG_WARNINGS) // The right way
   ...
if ((flags & (LOG_INCOMING | LOG_OUTGOING)) // Test for multiple flags set
         == (LOG_INCOMING | LOG_OUTGOING))
   ...

您还可以搜索C++ Triks

答案 1 :(得分:30)

当您想要在单个数据值中存储(并随后提取)不同数据时,使用位屏蔽是“有用的”。

我之前使用的一个示例应用程序是想象您将颜色RGB值存储在16位值中。所以看起来像这样:

RRRR RGGG GGGB BBBB

然后,您可以使用位掩码来检索颜色组件,如下所示:

  const unsigned short redMask   = 0xF800;
  const unsigned short greenMask = 0x07E0;
  const unsigned short blueMask  = 0x001F;

  unsigned short lightGray = 0x7BEF;

  unsigned short redComponent   = (lightGray & redMask) >> 11;
  unsigned short greenComponent = (lightGray & greenMask) >> 5;
  unsigned short blueComponent =  (lightGray & blueMask);

答案 2 :(得分:3)

假设我有32位ARGB值,每通道8位。我想用另一个alpha值替换alpha分量,例如0x45

unsigned long alpha = 0x45
unsigned long pixel = 0x12345678;
pixel = ((pixel & 0x00FFFFFF) | (alpha << 24));

掩码将前8位变为0,其中旧的alpha值为。将alpha值向上移动到它将采用的最终位位置,然后将其OR进入屏蔽像素值。最终结果是0x45345678,它存储在像素中。

答案 3 :(得分:3)

如果要在一个数字中编码多层信息,则使用位掩码。

所以(假设unix文件权限)如果你想存储3级访问限制(读,写,执行),你可以通过检查相应的位来检查每个级别。

rwx
---
110

基数2中的110转换为基数10中的6。

因此,您可以轻松检查是否有人允许通过和“权限”字段读取文件并获得所需权限。

伪代码:

PERM_READ = 4
PERM_WRITE = 2
PERM_EXEC = 1

user_permissions = 6

if (user_permissions & PERM_READ == TRUE) then
  // this will be reached, as 6 & 4 is true
fi

您需要理解数字和逻辑运算符的二进制表示,以理解位字段。