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 0
s 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
Conversion from Void* to the Pointer of the Base Class
How to Call a Pointer-To-Member-Function
Initializing a Ublas Vector from a C Array
C++ System() Function - How to Collect the Output of the Issued Command
Variable or Field Declared Void
Erasing Vector::End from Vector
Specialization of 'Template<Class _Tp> Struct Std::Less' in Different Namespace
Free Function Versus Member Function
Why Implicit Conversion Is Harmful in C++
C++ Static_Cast Runtime Overhead
How to Use C++14 Features When Building Qmake Projects
How Could Comma Separated Initialization Such as in Eigen Be Possibly Implemented in C++
Default Member Values Best Practice
Very Simple Application Fails with "Multiple Target Patterns" from Eclipse
Shared_Ptr and Weak_Ptr Differences
Does C++11 Unique_Ptr and Shared_Ptr Able to Convert to Each Other's Type