Click here to Skip to main content
15,893,588 members
Articles / Programming Languages / C#
Article

C# Bitwise Helper Class

Rate me:
Please Sign up or sign in to vote.
3.76/5 (16 votes)
1 Feb 20061 min read 77.8K   1.7K   30   2
A class that helps with some basic bitwise operations.

Introduction

I have been recently working on a project that requires a lot of low level programming. Reading and writing not of just bytes but the bits in those bytes as well. The .NET framework provides bitwise operators for dealing with values less than a byte. Unfortunately, the .NET framework does not have any easy way of doing some of the things we are going to be doing repeatedly in our project while dealing with bits (at least as far as I can tell) (besides, the BitArray class and the BitArray class don't provide out of the box functionality of some of the things). If there are things in the framework that already do this stuff, please send me an e-mail. So we have created a class called the BitHelper to help us with some of our basic operations dealing with bits.

The class we created contains methods for some of the primitive types (unsigned byte, short, int, long). These are all I needed for the project. Maybe later I can add overloads for all primitives. Or maybe someone can do it for me and e-mail me the code. There are six basic methods for each primitive type, with several overrides. The methods provided are (using the int data type and I did not include the overrides):

C#
///Gets the size of int in bits.
public static int SizeOf ( int pInput );
C#
///Gets the bits at the specified location
public static int GetBits ( int pInput, int pStartIndex, 
                                          int pLength );
C#
///Sets the bits at the specified location
public static int SetBits ( int pDest, int pSource, 
       int pSourceIndex, int pDestIndex, int pLength );
C#
///Checks to see if the bit is set at the specified position
public static bool IsBitSet ( int pInput, int pPosition);
C#
///Xor the value of the bit at the specified location
public static int ChangeBit ( int pInput, int pPosition );
C#
///Set the value of the bit at the specified location
public static int SetBit ( int pInput, int pPosition, bool pOn );

There are also some methods that perform the same tasks as some of the Windows macros: HiByte, LoByte, HiWord, LoWord, MakeWord, etc.

There is a test console app that calls some of these methods and prints the output.

If anyone finds any bugs, has any improvements, knows of better ways to do this stuff, or has any feedback at all, please send me an e-mail at ziadelmalki@hotmail.com.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralBit Manipulation and SQL Compliancy Pin
Tim McCurdy7-Feb-06 4:17
Tim McCurdy7-Feb-06 4:17 
One of the things that should have been explained in here is what exactly a Bit is. A Bit is basically 1 unit of the tinyest part of a Byte Poke tongue | ;-P . How can Bits be used you ask? Well, think of it as a string of 1's and 0's. Lets say you have a Byte which is 8 Bits, the string representation would be: 00000000. If I set Bit 1, the string is: 00000001. Notice how Bits are read from Right to Left. The same goes for 32 and 64 Bit values, it's just that the string representation is much longer.

Now, let's say we have a Table in a Database that is storing all the Roles a User can have and the IDs in that table are 1 - 32. There are usually 2 techniques for storing roles: 1.) use a single column in the User's table, 2.) use another X-Ref (cross-reference) table to store all the roles for a User.

If we're using SQL Server, there are only 2 datatypes which support Bit manipulation (Int and BigInt). An Int datatype can store 32 bits, and a BigInt 64 bits. So, if we can assume that there will be 32 or less user roles, then Int is good, otherwise we can use a BigInt datatype for 64 or less roles. So, let's assume we're using a single "SecurityAccess" column in the User's table.

Here's where I see programmers fall short and use Bits incorrectly. Even though you can store 32 Bits, the Int datatype is a Signed Integer so it's Max Value is 2 ^ (31 - 1) or 30 bits. What? We can't use all 32 bits for storage? Yes, you can. Remember that an Integer is a Signed value, which means it stores a Bit for a Positive and a bit for a Negative...which means it can also accept Negative values! What most people try to do is store the Bits 1 - 32 and then they get Arithmatic Overflow Errors. The correct way to set Bits is to always subtract 1 from the Bit you want to set. For example, if I want to set Bit "1" in an Integer value, I would set: int MySecurity = Math.Pow(2, Bit - 1);. Where this will never work is on the 32nd Bit. In this case, we need to reverse the Power of 2 to be -2 (remeber, Ints accept negative values).

Usually, programmmers need to set more than 1 Bit using Or-ing and Xor-ing. Here are some similar functions to those in the article that may be easier to read. Also take notice that if Bit 64 is trying to be set, instead of using the Power of 2, it uses the Power of -2. This is correct when you have a Signed Integer (i.e. when you need to save the value to a Database field). Most databases do not support UInts (Unsigned Ints).

For those of you who do not know one .NET Language or the other, I've converted for both:

VB.NET
'Function to Return whether or not a Bit is Set in a Value
Public Function BitIsSet(ByVal Value As Long, ByVal Bit As Integer) As Boolean
     If (Bit <= 0) Then Return False
     Dim nPwr As Integer = CInt(IIf(Bit = 64, -2, 2))       'Determine what Power of 2 to use
     Return ((CLng(Math.Pow(nPwr, Bit - 1)) And Value) > 0)
End Function

'Routine to Set a Bit
Public Sub BitSet(ByRef Value As Long, ByVal Bit As Integer, ByVal BitValue As Boolean)
     If (Bit <= 0) Then Return
     Dim nPwr As Integer = CInt(IIf(Bit = 64, -2, 2))
     If (BitValue) Then
          Value = Value Or CLng(Math.Pow(nPwr, Bit - 1))
     Else
          Value = Value And Not CLng(Math.Pow(nPwr, Bit - 1))
     End If
End Sub


C#
// Function to Return whether or not a Bit is Set in a Value
public bool BitIsSet(long Value, int Bit) {
     if (Bit <= 0) return false;
     int nPwr = (int)(Bit == 64 ? -2 : 2); // Determine what Power of 2 to use
     return (((long)Math.Pow(nPwr, Bit - 1)) & Value) > 0;
}

// Routine to Set a Bit
public void BitSet(ref long Value, int Bit, bool BitValue) {
     if (Bit <= 0) return;
     int nPwr = (int)(Bit == 64 ? -2 : 2); // Determine what Power of 2 to use
     if (BitValue)
          Value |= (long)(Math.Pow(nPwr, Bit - 1));
     else
          Value ~= (long)(Math.Pow(nPwr, Bit - 1));
}


Now, real quick, let's see how we might see which Users in our Database have the Bits 1 and 32 set. Cool | :cool:

Declare @Access BigInt
Set @Access = Power(2, 1 - 1) | Power(-2, 32 - 1)
Select * From dbo.Users
Where (Users.SecurityAccess & @Access) <> 0
Order By UserName


Tada! Simple!

Well, I hope I've made my point come across clearly because I know I had many problems with Bits until it finally clicked!

One thing to keep in mind is that if a User in our Database has all 32 Bits set, the integer representation would actually be -1! So if you get that value in your tests, you can be sure that you are correct! Depending on which Bits are actually set, you may come accross values that are really big negative values, this is also correct! Smile | :)

Happy coding!
GeneralMissing ! Pin
ziade3-Feb-06 12:45
ziade3-Feb-06 12:45 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.