Mask (computing)
From Wikipedia, the free encyclopedia
In computer science, a mask is some data that, along with an operation, is used in order to extract information stored elsewhere.
The most common mask used, also known as a bitmask, extracts the status of certain bits in a binary string or number. For example, if we have the binary string 10011101
and we want to extract the status of the fifth bit counting along from the most significant bit, we would use a bitmask such as 00001000
and use the bitwise AND
operator. Recalling that 1 AND 1 = 1
, with 0
otherwise, we find the status of the fifth bit, since
10011101 AND 00001000 = 00001000
Likewise we can set the fifth bit by applying the mask to the data using the OR
operator.
Similarly, we can use a sequence of binary numbers with a piece of data of equal length used to inform as to what parts of the data should be examined. With the bitwise operation (NOT X) AND Y
, a 1
in the mask (X
) instructs that the binary datum below (Y
) should be ignored, while 0
s in the mask (X
) tell that the data below (Y
) are to be examined. A common type of mask of this type is a subnetwork mask, which is associated with a device's IP address and used to instruct a router which bits of the address indicate the subdivision of the network the computer is on and which identify the specific computer within the subnetwork.
Contents |
[edit] Common bitmask functions
[edit] Masking bits to 1
To turn certain bits on, we use the bitwise OR
operation. Recall that Y or 1 = 1
and Y or 0 = Y
. Therefore, to make sure a bit is on, we OR
it with a 1
. To leave a bit alone, we OR
it with a 0
.
[edit] Masking bits to 0
As we see above, there is no way to change a bit from on to off using the OR
operation. Instead, we use bitwise AND
. When a value is AND
ed with a 1
, the result is simply the original value, as in: Y AND 1 = Y
. However, when we AND
a value with 0
, we are guaranteed to get a 0
back so we can turn a bit off by AND
ing it with 0
: Y AND 0 = 0
. To leave the other bits alone, simply AND
them with a 1
.
[edit] Querying the status of a bit
You can also use bitmasks to easily check the state of individual bits regardless of the other bits. To do this, you simply turn off all the other bits using the bitwise AND
as discussed above and see if the resulting value is 0
. If it is, then the bit was off, but if the value is any other value, then the bit was on. What makes this so convenient is that you do not need to figure out what the value actually is, you just need to know that it is not 0
.
[edit] Toggling bit values
So far we have seen how to turn bits on and turn bits off, but not both at once. What if we do not really care what the value is, we just know we want it to be the opposite of what it currently is? We can do this using the XOR
(exclusive or) operation. XOR
returns 1
if and only if an odd number of bits are 1
. Therefore, if two corresponding bits are 1
, the result will be a 0
, but if only one of them is 1
, the result will be 1
. Therefore we can invert the values of bits by XOR
ing them with a 1
. If the original bit was 1
, we will get 1 XOR 1 = 0
. If the original bit was 0
we will get 0 XOR 1 = 1
. Also note that XOR
masking is bit-safe, meaning it will not affect unmasked bits because Y XOR 0 = Y
, just like an OR
.
[edit] Arguments to functions
In programming languages such as C, bit masks are a useful way to pass a set of named boolean arguments to a function. For example, in the graphics API OpenGL, there is a command, glClear()
which clears the screen or other buffers. It can clear up to four buffers (the color, depth, accumulation, and stencil buffers), so the API authors could have had it take four arguments. But then a call to it would look like
glClear(1,1,0,0); // This is not how glClear actually works and would make for unreadable code.
which is not very descriptive. Instead there are four defined bit fields, GL_COLOR_BUFFER_BIT
, GL_DEPTH_BUFFER_BIT
, GL_ACCUM_BUFFER_BIT
, and GL_STENCIL_BUFFER_BIT
and glClear()
is declared as
void glClear(GLbitfield mask);
Then a call to the function looks like this
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Internally, a function taking a bitfield like this can use logical and
to extract the individual bits. For example, an implementation of glClear()
might look like
void glClear(GLbitfield mask) { if (mask & GL_COLOR_BUFFER_BIT) { // Clear color buffer. } if (mask & GL_DEPTH_BUFFER_BIT) { // Clear depth buffer. } if (mask & GL_ACCUM_BUFFER_BIT) { // Clear accumulation buffer. } if (mask & GL_STENCIL_BUFFER_BIT) { // Clear stencil buffer. } }
While elegant, in the simplest implementation this solution is not type-safe. A GLbitfield
is simply defined to be an unsigned int
, so the compiler would allow a meaningless call to glClear(42)
or even glClear(GL_POINTS)
. In C++ an alternative would be to create a class to encapsulate the set of arguments that glClear can accept. However, such an attempt at type safety would be at the cost of complexity.