如何使用位掩码?

Ani*_*mea 53 c++ bitmask c++11

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

goG*_*Gud 102

简言之,位掩码有助于操纵多个值的位置.这里有一个很好的例子;

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;



**
Run Code Online (Sandbox Code Playgroud)

警告:如果设置了一个标志,请不要使用等于运算符(即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))
   ...
Run Code Online (Sandbox Code Playgroud)

您还可以搜索C++ Triks


Dut*_*tts 33

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

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

RRRR RGGG GGGB BBBB
Run Code Online (Sandbox Code Playgroud)

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

  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);
Run Code Online (Sandbox Code Playgroud)


til*_*l_b 6

当您想要在单个数字中编码多层信息时,可以使用位掩码。

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

rwx
---
110
Run Code Online (Sandbox Code Playgroud)

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

因此,您可以轻松地检查是否允许某人读取该文件,方法是将权限字段与所需的权限进行“和”操作。

伪代码:

PERM_READ = 4
PERM_WRITE = 2
PERM_EXEC = 1

user_permissions = 6

if ((user_permissions & PERM_READ) == PERM_READ) then
  // this will be reached, as 6 & 4 is true
fi
Run Code Online (Sandbox Code Playgroud)

您需要对数字和逻辑运算符的二进制表示有一定的了解才能理解位字段。


Nei*_*irk 5

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

unsigned long alpha = 0x45
unsigned long pixel = 0x12345678;
pixel = ((pixel & 0x00FFFFFF) | (alpha << 24));
Run Code Online (Sandbox Code Playgroud)

掩码将前 8 位变为 0,即旧的 alpha 值所在的位置。alpha 值被向上移动到它将采用的最终位位置,然后它被 OR 运算到掩码像素值中。最终结果是 0x45345678 存储到像素中。