C++ 如何使用位掩码?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18591924/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 22:03:30  来源:igfitidea点击:

How to use bitmask?

c++c++11bitmask

提问by Animea Animea

How do i use it in C++ ? when is it useful to use ?
Please give me an example of a problem where bitmask is used , how it actually works . Thanks!

我如何在 C++ 中使用它?什么时候有用?
请给我一个使用位掩码的问题的例子,它是如何工作的。谢谢!

采纳答案by Dutts

Bit masking is "useful" to use when you want to store (and subsequently extract) different data within a single data value.

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

An example application I've used before is imagine you were storing colour RGB values in a 16 bit value. So something that looks like this:

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

RRRR RGGG GGGB BBBB

You could then use bit masking to retrieve the colour components as follows:

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

  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);

回答by goGud

Briefly bitmask helps to manipulate position of multiple values. There is a good example here ;

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

Bitflags are a method of storing multiple values, which are not mutually exclusive, in one variable. You've probably seen them before. Each flag is a bit position which can be set on or off. You then have a bunch of bitmasks #defined for each bit position so you can easily manipulate it:

位标志是一种将多个值存储在一个变量中的方法,这些值并不相互排斥。你可能以前见过它们。每个标志都是一个位位置,可以设置为开或关。然后,您为每个位位置定义了一堆位掩码,以便您可以轻松操作它:

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



**

WARNING: DO NOT use the equality operator (i.e. bitflags == bitmask) for testing if a flag is set - that expression will only be true if that flag is set and all others are unset. To test for a single flag you need to use & and == :

警告:不要使用相等运算符(即 bitflags == 位掩码)来测试是否设置了标志 - 只有在设置了该标志并且所有其他标志都未设置时,该表达式才会为真。要测试单个标志,您需要使用 & 和 == :

**

**

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))
   ...

You can also search C++ Triks

您还可以搜索C++ Triks

回答by Neil Kirk

Let's say I have 32-bit ARGB value with 8-bits per channel. I want to replace the alpha component with another alpha value, such as 0x45

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

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

The mask turns the top 8 bits to 0, where the old alpha value was. The alpha value is shifted up to the final bit positions it will take, then it is OR-ed into the masked pixel value. The final result is 0x45345678 which is stored into pixel.

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

回答by til_b

Bitmasks are used when you want to encode multiple layers of information in a single number.

当您想在一个数字中对多层信息进行编码时,可以使用位掩码。

So (assuming unix file permissions) if you want to store 3 levels of access restriction (read, write, execute) you could check for each level by checking the corresponding bit.

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

rwx
---
110

110 in base 2 translates to 6 in base 10.

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

So you can easily check if someone is allowed to e.g. read the file by and'ing the permission field with the wanted permission.

所以你可以很容易地检查是否有人被允许读取文件,例如通过使用所需的权限来读取权限字段。

Pseudocode:

伪代码:

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

You need a working understanding of binary representation of numbers and logical operators to understand bit fields.

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