How to Use Bitmask

How can I use a bitmask?

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:

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

How to use bitmasks to allow/disallow manipulation of certain bits

Assuming a C-like language where & is bitwise-and; | is bitwise-or; and ~ is bitwise-complement:

new_value = (value & locked) | (incoming & ~locked);

You could use + instead of |, if you felt it was more readable.

How and Where to use Bit Mask in java

The result value for the operator & is the bitwise AND of the operand values.

It means that when applied to two integers (in binary representation), it will result in an integer where each bit will be set to 1 only if both bits at the same position where 1, else to 0.

int a =     0b01010111;
int b = 0b11111111;
//result in 0b01010111

System.out.println(a & b);//print 87 which is decimal representation of 0101 0111

Now if you understood my explanation, the example you show us is the equivalent of

if(true)//because 1 == 1 will always be true.

As doing an & on two same numbers (1 and 1) will automatically return this number (in that case 1).

How do I make a bit mask that only masks certain parts (indices) of 32 bits?

first of all about representation. You need binary numbers to represent bits and masks. There are no binaries implemented directly in c/c++ languages at least before c++14. So, before c++14 you had to use hexadecimals or octals to represent your binaries, i.e.

0000 1111 == 0x0F
1111 1010 == 0xFA

since c++14 you can use

0b00001111;

Now, if you shift your binary mask left or right, you will have the following pictures

00001111 (OxF) << 2 ==> 00111100 (0x3C)
00001111 (0xF) >> 2 ==> 00000011 (0x03)

Now, supposedly you have an number in which you are interested in bits 4 to 7 (4 bits)

int bad = 0x0BAD; // == 0000 1011 1010 1101

you can create a mask as

int mask = 0x00F0; // == 0000 0000 1111 00000

and do bitwise and

int result = bad & mask; // ==> 0000 0000 1010 000 (0x00A0)

You will mask 4 bits in the middle of the word, but it will print as 0xA0. probably not what you would expect. To print it as 0xA you would need to shift the result 4 bits right: result >> 4. I prefer doing it in a bit different order, shifting the 'bad' first and then mask:

int result = (bad >> 4) & 0xF;

I hope the above will help you to understand bits.

How to use bitmasks to store boolean values in JavaScript

I am not sure if I am supposed to handle the "not" case

You're not supposed to handle it at all. A bitmask works so that you either have a bit with value 1 if your flag is set or the bit with value 0 if not. Given that your value starts with 0s everywhere (the integer 0), you just have to set the bit (by OR 1) when your condition is true and you don't have to do anything otherwise.

You could simplify your code to

function getInt(x, y, z) {
return (0b10 // a
| (x << 2) // 0b00100 if x and 0b00000 else
| (y << 3) // 0b01000 if y and 0b00000 else
| (z << 4)); // 0b10000 if z and 0b00000 else
}

C++ - Using Bitmask to get values from an int

To get only the 8 rightmost bits, you can do

int right8 = mynum & 0xFF;

Because you are anding the top 24 bits with 0, these will be set to 0, while the bottom 8 will retain their values as they will be anded with ones.

In order to get the next 8 rightmost, you will need to set bits 8-15 to one and all the other to zero in your bitmask. This will maintain the same bits in positions 8-15, but since you need them to be in the bottom 8 bits, you can simply bit shift them 8 positions to the right. You can do that with the following.

int next8 = myNum & 0xFF00;
int next8 = next8 >> 8;

Using a bitmask in C#

The traditional way to do this is to use the Flags attribute on an enum:

[Flags]
public enum Names
{
None = 0,
Susan = 1,
Bob = 2,
Karen = 4
}

Then you'd check for a particular name as follows:

Names names = Names.Susan | Names.Bob;

// evaluates to true
bool susanIsIncluded = (names & Names.Susan) != Names.None;

// evaluates to false
bool karenIsIncluded = (names & Names.Karen) != Names.None;

Logical bitwise combinations can be tough to remember, so I make life easier on myself with a FlagsHelper class*:

// The casts to object in the below code are an unfortunate necessity due to
// C#'s restriction against a where T : Enum constraint. (There are ways around
// this, but they're outside the scope of this simple illustration.)
public static class FlagsHelper
{
public static bool IsSet<T>(T flags, T flag) where T : struct
{
int flagsValue = (int)(object)flags;
int flagValue = (int)(object)flag;

return (flagsValue & flagValue) != 0;
}

public static void Set<T>(ref T flags, T flag) where T : struct
{
int flagsValue = (int)(object)flags;
int flagValue = (int)(object)flag;

flags = (T)(object)(flagsValue | flagValue);
}

public static void Unset<T>(ref T flags, T flag) where T : struct
{
int flagsValue = (int)(object)flags;
int flagValue = (int)(object)flag;

flags = (T)(object)(flagsValue & (~flagValue));
}
}

This would allow me to rewrite the above code as:

Names names = Names.Susan | Names.Bob;

bool susanIsIncluded = FlagsHelper.IsSet(names, Names.Susan);

bool karenIsIncluded = FlagsHelper.IsSet(names, Names.Karen);

Note I could also add Karen to the set by doing this:

FlagsHelper.Set(ref names, Names.Karen);

And I could remove Susan in a similar way:

FlagsHelper.Unset(ref names, Names.Susan);

*As Porges pointed out, an equivalent of the IsSet method above already exists in .NET 4.0: Enum.HasFlag. The Set and Unset methods don't appear to have equivalents, though; so I'd still say this class has some merit.


Note: Using enums is just the conventional way of tackling this problem. You can totally translate all of the above code to use ints instead and it'll work just as well.



Related Topics



Leave a reply



Submit