BlackWasp
.NET Framework
.NET 1.1

Bit Manipulation with the BitArray

The forty-second part of the C# Fundamentals tutorial examines the use of the BitArray class. This type of collection can be used to hold very large series of bits that can be manipulated either independently or collectively as an entire group.

The BitArray Collection

The BitArray collection allows the creation of large groups of Boolean values or bit fields. The collection is similar to other collection classes that have been discussed in the C# Fundamentals tutorial. However, the contents of the collection are not objects but Boolean values. This means that the behaviour of the class differs slightly.

Implemented Collection Interfaces

The BitArray collection implements the properties and methods of the ICollection interface. This behaviour is described in the earlier Collection Interfaces article. The rest of this article describes only the additional functionality provided by BitArray.

Declaring a BitArray

Constructors

The BitArray class is unusual in that it does not provide a constructor that has no parameters. This is because a BitArray collection must be fully initialised during construction. There are six constructors available, each populating the contents of the collection in a different manner. The simplest constructor creates a new BitArray containing a number of Boolean values that are all set to false. The number of bits to generate is passed as an integer parameter.

The BitArray class is found in the System.Collections namespace so to execute the examples, add using System.Collections; to the source code.

BitArray flags = new BitArray(16);

The previous constructor can be extending by passing a second, Boolean value. In this case, the created BitArray is sized according to the integer parameter and each element in the collection is set to the value of the second parameter.

BitArray flags = new BitArray(16, true);

The remaining four constructors allow a BitArray to be created with its entire contents initialised from existing values. The first of these is one of the simplest, permitting an array of Boolean values to be copied into the collection.

bool[] bits = new bool[] { true, false, false, true };

BitArray flags = new BitArray(bits);

foreach (bool flag in flags)
    Console.WriteLine(flag);

/* OUTPUT

True
False
False
True

*/

Instead of using an array of Boolean values to initialise a BitArray, an existing BitArray can be used for source data. This effectively creates a copy of the collection.

bool[] bits = new bool[] { true, false, false, true };

BitArray flags = new BitArray(bits);
BitArray copy = new BitArray(flags);

foreach (bool flag in copy)
    Console.WriteLine(flag);

/* OUTPUT

True
False
False
True

*/

The fifth constructor for the BitArray class allows its contents to be copied from an array of byte values. Each byte is split into eight bits within the created collection. The first byte is copied to the first eight bits of the BitArray with the least significant bit being the first item in the collection. The second byte is copied to items eight to fifteen and so on.

byte[] bytes = new byte[] { 1, 170 };

BitArray flags = new BitArray(bytes);

foreach (bool flag in flags)
    Console.WriteLine(flag);

/* OUTPUT

True
False
False
False
False
False
False
False
False
True
False
True
False
True
False
True

*/

The final constructor initialises the contents of the BitArray from an array of integer values. Integer values are thirty-two bit values so the first integer is copied into entries zero to thirty-one, the second integer into bits thirty-two to sixty-three and so on. For each integer, the least significant bit is copied first and the most significant bit is copied last.

int[] values = new int[] { 1, 32767 };

BitArray flags = new BitArray(values);

foreach (bool flag in flags)
    Console.WriteLine(flag);

/* OUTPUT

True
False
False
False
...

*/

Reading and Writing BitArray Contents

Reading Individual Bits

Single bit values can be extracted from a BitArray using the index number for a specific bit. The BitArray class implements the IEnumerable interface allowing the index to be appended to the collection name within square brackets for this purpose. The class also provides a Get method that accepts the index number as a parameter and returns the Boolean value of the bit at the specified position. Each method is demonstrated in the example below:

BitArray flags = new BitArray(new bool[] { true, false, false, true });

Console.WriteLine(flags[0]);                // Outputs "True"
Console.WriteLine(flags.Get(1));            // Outputs "False"

Writing Individual Bits

Single bits within a BitArray can be set and cleared individually. As with reading the individual bits, there are two manners that may be used. Firstly, the index value may be appended to the collection name and the value of a bit assigned directly. Secondly, the class provides a Set method. This method accepts an integer parameter for the index of the item to change and a Boolean indicating the new value. The following example shows both methods:

BitArray flags = new BitArray(16, false);

flags[0] = true;
flags.Set(1, true);

Writing Multiple Bits

Often you will want to set or clear all of the bits within a BitArray. This can be achieved using the SetAll method. The method requires a single parameter containing the new value that every bit within the collection will be set to.

BitArray flags = new BitArray(16);

flags.SetAll(true);

BitArray Length

As the BitArray class implements ICollection, it includes the Count property that returns the number of items currently held. In addition to this read-only property, BitArray provides the Length property that can be used to both request the number of items in the collection and to change the length.

When the Length property is set, the size of the BitArray may increase or decrease. If the new length is smaller than the existing number of items, the collection is truncated with all entries at indices equal to or higher than the new length being permanently erased. If the new length is larger than the current number of items then new items are appended to the BitArray. Each additional item is initially set to false.

BitArray flags = new BitArray(new bool[] { true, false, false, true });

Console.WriteLine(flags.Count);             // Outputs 4
Console.WriteLine(flags.Length);            // Outputs 4
flags.Length = 8;
Console.WriteLine(flags.Length);            // Outputs 8

Bitwise Operations

The key reason for creating BitArrays is the set of available bitwise operations. Four methods provide logical NOT, AND, OR and XOR (exclusive OR) functionality. The final sections of this article describe the use of these functions.

Not

The Not method performs a simple One's Complement operation against a BitArray. Every bit within the collection is inverted. ie. All true values are set to false and vice versa. The method requires no parameters.

BitArray flags = new BitArray(new bool[] { true, false, false, true });

flags.Not();

foreach (bool flag in flags)
    Console.Write("{0}\t", flag);

/* OUTPUT

False   True    True    False

*/

And

The And method performs a logical AND operation. Two BitArrays are required with one being passed as a parameter to the method. The contents of the collection used as a parameter are unaffected.

BitArray flags = new BitArray(new bool[] { true, false, false, true });
BitArray andFlags = new BitArray(new bool[] { false, true, false, true });

flags.And(andFlags);

foreach (bool flag in flags)
    Console.Write("{0}\t", flag);

/* OUTPUT

False   False   False   True

*/

Or

The Or method performs a logical OR operation. As with the And method, two BitArrays are required.

BitArray flags = new BitArray(new bool[] { true, false, false, true });
BitArray orFlags = new BitArray(new bool[] { false, true, false, true });

flags.Or(orFlags);

foreach (bool flag in flags)
    Console.Write("{0}\t", flag);

/* OUTPUT

True    True    False   True

*/

Xor

The final method to be considered provides a logical exclusive OR bitwise operation. The Xor method is similar in operation to And and Or, requiring one BitArray to be used as a parameter.

BitArray flags = new BitArray(new bool[] { true, false, false, true });
BitArray xorFlags = new BitArray(new bool[] { false, true, false, true });

flags.Xor(xorFlags);

foreach (bool flag in flags)
    Console.Write("{0}\t", flag);

/* OUTPUT

True    True    False   False

*/
Link to this Page24 June 2007
RSS RSS Feed