Set Specific Bit in Byte Array

34,699

Solution 1

The process of selecting a specific bit consists of two steps:

  • Picking the byte, and then
  • Picking the bit.

Picking the byte is simple: all you need to do is dividing the bit index by the number of bits in a byte - i.e. dividing by eight:

int byteIndex = bitIndex / 8;

Now that you know what byte to use, calculate which bit you want to access. For that you need to compute a remainder of a division by eight, like this:

int bitInByteIndex = bitIndex % 8;

With these two indexes in hand, it is easy to access the bit: use 1 << bitInByteIndex as a mask, like this:

byte mask = (byte)(1 << bitInByteIndex);
bool isSet = (bytes[byteIndex] & mask) != 0;
// set to 1
bytes[byteIndex] |= mask;
// Set to zero
bytes[byteIndex] &= ~mask;
// Toggle
bytes[byteIndex] ^= mask;

Solution 2

You could use a BitArray:

byte[] bytearray = new byte[16];

var bitArray = new BitArray(bytearray);

bitArray.Set(8, true);

bitArray.CopyTo(bytearray, 0);

Solution 3

Directly from a Byte Array, your quickest solution is probably using a BitArray. - http://msdn.microsoft.com/en-us/library/system.collections.bitarray.aspx

E.g. This would go something like:

public void BitManimulation() 
{
    //Ill just use 2 bytes here for demonstration, get your 16 bytes here.
    byte[] bytes = new[] { (byte)250, (byte)250 };

    //Convert your bytes to a BitArray.
    BitArray array = new BitArray(bytes);
    array[3] = !array[3]; // Flip
    array[4] = false; // 0
    array[5] = true; // 1

    //Convert back to bytes.
    byte[] bytes2 = new byte[2];
    array.CopyTo(bytes2,0);

    Console.WriteLine(bytes2[0]);
    Console.WriteLine(bytes2[1]);
}

Now this comes with a performance penalty.

So as an alternative you have the BitVector32 that will require you to convert blocks of 4 bytes to an integer... - http://msdn.microsoft.com/en-us/library/system.collections.specialized.bitvector32.aspx

Finally you can do bit shifting, XOR's etc to produce the desired results. Since @dasblinkenlight already left a nice answer for that ill just leave you with that for explaining things.^

Here is some quick helper methods based on his post though:

public static class ByteArrayExt
{
    public static byte[] SetBit(this byte[] self, int index, bool value)
    {
        int byteIndex = index / 8;
        int bitIndex = index % 8;
        byte mask = (byte)(1 << bitIndex);

        self[byteIndex] = (byte)(value ? (self[byteIndex] | mask) : (self[byteIndex] & ~mask));
        return self;
    }

    public static byte[] ToggleBit(this byte[] self, int index)
    {
        int byteIndex = index / 8;
        int bitIndex = index % 8;
        byte mask = (byte)(1 << bitIndex);

        self[byteIndex] ^= mask;
        return self;
    }

    public static bool GetBit(this byte[] self, int index)
    {
        int byteIndex = index / 8;
        int bitIndex = index % 8;
        byte mask = (byte)(1 << bitIndex);

        return (self[byteIndex] & mask) != 0;
    }
}

Solution 4

First you need to find out which byte you're working with. Let's say you have:

00000000 00000000 00000000 00000000 ...

And you want to turn on the 10th bit, so it needs to become like this:

00000000 01000000 00000000 00000000 ...

So first do a division by 8 (rounded down) to locate the byte number (in this case byte number one, or the second byte). Once you've done that, you can use bitwise operators to set the bit you want, i.e.

array[1] |= 0x40

We're doing a bitwise OR operation between the old value of that byte and 0x40 (which is 01000000). If the old value was 00101101, then array[1] = (00101101 OR 01000000), which is 01101101.

Naturally, in this case I've been using literals so you'll have to change that depending on which bit is set (e.g. if you're setting the bit before the last, you want to use 0x02 instead, etc.

Solution 5

Dividing the bit number by 8 gives you the byte. Taking it modulo 8 give you the bit number within the byte.

Share:
34,699
Nevets
Author by

Nevets

Updated on September 26, 2020

Comments

  • Nevets
    Nevets over 3 years

    I want to know how to set a specific bit in a 16 byte array (128 bits).

    For example ... if I wanted to set the 9th bit in the the array I would expect:

    {00, 80, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00}

    If I wanted to set the 125th bit ...

    {00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 08}

    I have looked into using bit shifting but got confused on how to bit shift with an array consisting of 128 bits. Is there a way to break down an array this size and evaluate in smaller chunks of bytes? Any help would be appreciated.

  • Nevets
    Nevets about 10 years
    One additional question ... is there a way to set the new bytes into an array? For example once the nth bit is set can I reconstruct the 16 byte array including the newly set bit?
  • Sergey Kalinichenko
    Sergey Kalinichenko about 10 years
    @Nevets Yes, adding elements to an array is possible in .NET (see this answer). However, if you are planning to grow the array a lot, consider using a List<byte> instead. There is also a BitArray class that may very well be worth checking out.
  • johnnycardy
    johnnycardy over 8 years
    It may also be worth checking that byteIndex is within the bounds of the bytes array ie. byteIndex < bytes.Length
  • Assimilater
    Assimilater almost 7 years
    This is what I was looking for by googling this question
  • Wolfsblvt
    Wolfsblvt over 4 years
    I am not sure if I understand something wrong, but for me this one didn't work. With bitInByteIndex = 0 it flipped the last byte, so it was 00000001. But I wanted the first byte. So I just turned the mask condition around and it worked for me: var mask = (byte) (1 << (7 - bitInByteIndex));
  • Sergey Kalinichenko
    Sergey Kalinichenko over 4 years
    @Wolfsblvt Bits are conventionally counted from the least significant one starting with place value of 1, then 2, then 4, and so on. Bit zero is all the way in the back. If you number bits left-to-right, the way you did it (subtracting index from seven) is indeed the right way to go.
  • Wolfsblvt
    Wolfsblvt over 4 years
    @dasblinkenlight That explains a lot, thank you! I just thought that index in this answer meant like if you had a bit array, and just go over all of them. That was confusing me. I needed to switch bits that are meant to display pixels in a bitmap, so I needed left-to-right.