• Bit level functionality in C#

    by  • February 17, 2012 • .Net, Articles, Programming • 5 Comments

    Low level operations are commonplace for embedded developers but usually are overlooked by application level developers, but they still offer some useful quirks. After reading a few articles I decided to port some of the most common and useful bit level hacks to C#.

    More information about the built in operators that are found in C# can be found on MSDN and the basis of this article can be found here along with additional info on how each of the bit level operations were performed.

    Checking whether an integer is even

    One of the most common and easy to understand operations is checking whether a value is even or odd. This is done by checking whether the least significant bit is 1 (odd) or 0 (even). This is done by AND-ing the value with 1 (00000001). The result will be 0 if even or 1 for odd.

    As we are AND-ing with 1 (00000001) only a comparison is made on the least significant bit, thus this method works whatever value the input number is.

    /// <summary>
    /// Indicates whether a value is even.
    /// </summary>
    /// <param name="value">The number to check</param>
    /// <returns>Returns whether the number is even</returns>
    public static bool IsEven(int value)
    {
        return (value & 1) == 0;
    }
    

    Check whether a Bit is set.

    Some applications use an integer as a set of bit flags, C# does provide some limited functionality for this but here is an easy way to check whether a bit at a specific index is set.

    Whether this and following methods ask for an index parameter, I check whether it is in range. I use the sizeof() function on the int as it could be different depending on whether you are working on a 32 or 64bit system.

    This uses the shift operator << to move 1 bit back a specific number of places and then using the previous IsEven trick to determine whether the bit is set.

    /// <summary>
    /// Indicates whether a bit is set in a signed integer
    /// </summary>
    /// <param name="value">The number to check</param>
    /// <param name="index">The bit index in the integer</param>
    /// <returns>Returns whether the bit is set</returns>
    public static bool IsBitSet(int value, int index)
    {
        if (index < 0 || index >= sizeof(int) * 8)
        {
            throw new ArgumentOutOfRangeException();
        }
    
        return (value & (1 << index)) == 1;
    }
    

    Set a Bit
    Carrying on with the concept of using bit flags, this method sets a bit to 1 at a specific index in the bit array representing the integer.

    Instead of performing a check, we use the OR operator | to set the value. This works because using the OR operator, the bit value will always be set, regardless of the original bit value. e.g. 0 OR 1 = 1, 1 OR 1 = 1

    /// <summary>
    /// Sets a bit at a specified index in a signed integer
    /// </summary>
    /// <param name="value">The number to use</param>
    /// <param name="index">The bit index in the integer</param>
    /// <returns>Returns the new value</returns>
    public static int SetBit(int value, int index)
    {
        if (index < 0 || index >= sizeof(int) * 8)
        {
            throw new ArgumentOutOfRangeException();
        }
    
        return value | (1 << index);
    }
    

    Unset a Bit

    This does the opposite of the last method, it sets a value to 0 at a specific index in a bit array.

    The method used is a bit different but still along the same lines.

    Instead of using the shifted bit value, e.g. 1 << 4 = 00010000 we use ~(1 << n) which means all values are 1 apart from the index value which is 0 e.g. ~(1 << 4) = 11101111

    By AND-ing this with the original value we only set the index value to zero as anything AND’ed with 0 is always 0.

    /// <summary>
    /// Unsets a bit at a specified index in a signed integer
    /// </summary>
    /// <param name="value">The number to use</param>
    /// <param name="index">The bit index in the integer</param>
    /// <returns>Returns the new value</returns>
    public static int UnsetBit(int value, int index)
    {
        if (index < 0 || index >= sizeof(int) * 8)
        {
            throw new ArgumentOutOfRangeException();
        }
    
        return value & ~(1 << index);
    }
    

    Toggle a Bit

    To toggle the value (1 to 0 or 0 to 1) based on the original value could be done via a combination of calls to the existing functions:

    if (IsBitSet(value, index))
    {
        return UnsetBit(value, index);
    }
    else
    {
        return SetBit(value, index);
    }
    

    However this can be done just by using bit level operations without the need for a condition statement.

    /// <summary>
    /// Toggles a bit at a specified index in a signed integer
    /// </summary>
    /// <param name="value">The number to use</param>
    /// <param name="index">The bit index in the integer</param>
    /// <returns>Returns the new value</returns>
    public static int ToggleBit(int value, int index)
    {
        if (index < 0 || index >= sizeof(int) * 8)
        {
            throw new ArgumentOutOfRangeException();
        }
    
        return value ^ (1 << index);
    }
    

    Isolate right most set bit

    This one takes a bit of explaining. This finds the rightmost 1-bit and sets all the other bits to 0. The end result has only that one rightmost 1-bit set.

    For example 10111100 would return 00000100

    /// <summary>
    /// Isolates the rightmost 1-bit and sets all the other bits to 0
    /// </summary>
    /// <param name="value">The number to use</param>
    /// <returns>Returns the new value</returns>
    public static int IsolateRightmostSetBit(int value)
    {
        return value & (-value);
    }
    

    Being nice I have placed all these methods in a class that can be downloaded directly from my site.

    About

    Software engineer. Tea drinker

    http://MrPfister.com

    5 Responses to Bit level functionality in C#

    1. Graham
      February 17, 2012 at 9:40 pm

      But what about the [FlagsAttribute] you can use on an enum to turn it into a type safe bitfield?

      • February 17, 2012 at 10:24 pm

        Using the FlagsAttribute (http://msdn.microsoft.com/en-us/library/system.flagsattribute(v=vs.100).aspx) does allow bitwise operators but it has a few drawbacks; when handling large enums (if you want to make a 64 element enum be my guest) and more importantly if the data is being processed dynamically. Using an enumeration is good if the data is predefined and thus the enum elements can match up with the input data, but Microsoft says it is a no no to future proof enums with dummy values.

    2. Roland
      February 2, 2013 at 8:37 am

      I think there is a mistake in the IsBitSet method. The return statement should probably look like this:

      return (value & (1 << index)) == (1 << index);

      • Cyril
        August 9, 2013 at 11:08 am

        you can check only if the value is different from 0

        return (value&(1<<index))!=0;

    3. Cyril
      August 9, 2013 at 11:14 am

      For the IsolateRightmostSetBit, it doesn’t works for a power of 2 value.
      exemple:
      16 (10000)
      16 – 1 = 15 (01111)
      10000 & 01111 = 0

      But this is a usefull trick to chek if the value is a power of 2 (just add the test for 0 and it’s fine)

    Leave a Reply

    Your email address will not be published. Required fields are marked *