-3

For all the definitions I've seen of bit masking, they all just dive right into how to bit mask, use bitwise, etc. without explaining a use case for any of it. Is the purpose of updating all the bits you want to keep and all the bits you want to clear to "access an array" in bits?

  • 1
    Code like `unsigned a; ... a |= 1;` is not necessarily conceptually accessing an _array_ of bits. That code simply insures `a` is odd. – chux - Reinstate Monica Aug 08 '18 at 16:14
  • 2
    What do you mean by "accessing an array" of bits? Please give a code example. Currently this question is unclear – Support Ukraine Aug 08 '18 at 16:20
  • in some situations I think the operands can be considered just series of bits – phuclv Aug 08 '18 at 16:24
  • There are other ways to view some specific masking operations, such as rounding down to a multiple of a power of two or remainder by a power of two. Of course you can always view it as bit-array manipulation too. – harold Aug 08 '18 at 16:25

2 Answers2

1

Is the purpose of updating all the bits you want to keep and all the bits you want to clear to "access an array" in bits?

I will say the answer is no.

When you access an array of int you'll do:

int_array[index] = 42;  // Write access
int x = int_array[42];  // Read access

If you want to write similar functions to read/write a specific bit in e.g. an unsigned int in a "array like fashion" it could look like:

unsigned a = 0;
set_bit(a, 4);   // Set bit number 4
unsigned x = get_bit(a, 4); // Get bit number 4

The implementation of set_bit and get_bit will require (among other things) some bitwise mask operation.

So yes - to access bits in an "array like fashion" you'll need masking but...

There are many other uses of bit level masking.

Example:

int buffer[64];
unsigned index = 0;

void add_to_cyclic_buffer(int n)
{
    buffer[index] = n;
    ++index;
    index &= 0x3f;  // Masking by 0x3f ensures index is always in the range 0..63
}

Example:

unsigned a = some_func();

a |= 1;  // Make sure a is odd
a &= ~1; // Make sure a is even

Example:

unsigned a = some_func();

a &= ~0xf;  // Make sure a is a multiple of 16

This is just a few examples of using "masking" that has nothing to do with accessing bits as an array. Many other examples can be made.

So to conclude:

Masking can be used to write functions that access bits in an array like fashion but masking is used for many other things as well.

Support Ukraine
  • 42,271
  • 4
  • 38
  • 63
0

So there are 3 (or 4) main uses.

One, as you say, is where you use the word as a set of true/false flags, where each flag is just indexed in a symmetric manner. I use 'word' here to be the piece of discrete memory that you are accessing in a single operation. So a byte holds 8 bit values, and a 'long long' holds 64 bits. With a bit more effort an array of words can be used as an array of more packed flags.

A second is where you are doing some manipulation of the value, but still consider the word to hold one value. There are many tricks like setting or clearing bottom bits to ensure alignment, or clearing top bits to get a modulus, shifting to divide or multiply by powers of 2.

A third use is where you want to pack lots of smaller-ranged values into a word. Each of the values is a particular meaning in context. This may either be because you need to communicate with a device that has defined this as the protocol, or because you need to create so many objects that the saving in space in each object outweighs the increase in code size and code speed cost (though that might be contrasted with the increased cache misses causing slowdown if the object were bigger).

As a distinction the fourth case is where these fields are distinct 1-bit flags that have specific meanings in the context of the code. Data objects tend to collect a number of such flags, and it is simply more convenient sometimes to store them as bits in a single location, than to use separate bytes for each flag. Generally testing a particular fixed indexed bit, or a fixed masked bit is no more expensive in code size or speed than testing the whole byte, though writing can be more complex. The storage savings are clear, so often programmers will declare an enumeration of bit masks by default when faced with creating a number of flags in a structure, or when writing a function.

Gem Taylor
  • 5,381
  • 1
  • 9
  • 27