HOWTO: General Bit Manipulation Routines

ID: Q185554

The information in this article applies to:

SUMMARY

This article outlines routines to set or reference individual bits in both a variable and an array.

MORE INFORMATION

Microsoft provides programming examples for illustration only, without warranty either expressed or implied, including, but not limited to, the implied warranties of merchantability and/or fitness for a particular purpose. This article assumes that you are familiar with the programming language being demonstrated and the tools used to create and debug procedures. Microsoft support professionals can help explain the functionality of a particular procedure, but they will not modify these examples to provide added functionality or construct procedures to meet your specific needs. If you have limited programming experience, you may want to contact the Microsoft fee-based consulting line at (800) 936-5200. For more information about the support options available from Microsoft, please see the following page on the World Wide Web:

   http://www.microsoft.com/support/supportnet/refguide/default.asp

This article provides a set of general bit-manipulation routines for use in VBA code. NOTE: You should write a Visual C or C++ DLL to do bit manipulation if you require high performance. The routines are:

   Name           Description
   -----------------------------------------------------------------------

   BitMask        Returns a mask used by the other routines to set or test
                  the value of a bit in a variable.

   BitSet         Turns a bit "on" or "off".

   BitFlip        Changes the state of a bit.

   BitTest        Returns the state of a bit.

   ArrayBitSet    Turns a bit "on" or "off".

   ArrayBitFlip   Changes the state of a bit.

   ArrayBitTest   Returns the state of a bit.

The Array routines assume 32 bits per element, starting with bits 0..31 in the lowest element, bits 32..63 in the second element, and so forth. The array does not have to be 0-based. If you specify a bit number that falls outside the bounds of the array, the operation leaves the data unchanged.

The routines have one or more of the following parameters:

   X        A Long value containing 32 bits to be manipulated.

   A()      An array containing bits to be manipulated.

   Value    TRUE to set a bit, FALSE to reset a bit.

   N        A number indicating the bit to manipulate. In the case of a
            single Long variable, valid ranges are 0..31. In the case of an
            array, valid values are 0..(number of elements * 32) - 1. Any
            value of N outside this range is ignored. In the case of a
            function, a FALSE is returned.

The BitTest and ArrayBitTest functions return TRUE (-1) if the bit is 1 and FALSE (0) if the bit is 0 (zero).

Sample Code

1. Create a new project and add the following code to a module:

      Function BitMask(ByVal N As Long) As Long
      Dim I As Long, Mask As Long
        If N < 0 Or N > 31 Then
          BitMask = 0
        ElseIf N = 31 Then
          BitMask = &H80000000
        Else
          Mask = 1
          For I = 1 To N
            Mask = Mask + Mask
          Next I
          BitMask = Mask
        End If
      End Function

      Sub BitSet(X As Long, ByVal N As Long, ByVal Value As Boolean)
        If Value Then
          X = X Or BitMask(N)
        Else
          X = X And Not BitMask(N)
        End If
      End Sub

      Sub BitFlip(X As Long, ByVal N As Long)
        X = X Xor BitMask(N)
      End Sub

      Function BitTest(X As Long, ByVal N As Long) As Boolean
      ' Return False if invalid N
        BitTest = (X And BitMask(N)) <> 0
      End Function

      Sub ArrayBitSet(A() As Long, ByVal N As Long, _
                      ByVal Value As Boolean)
      Dim Element As Integer
        Element = N \ 32 + LBound(A)
        If Element <= UBound(A) And N >= 0 Then
          BitSet A(Element), N Mod 32, Value
        End If
      End Sub

      Sub ArrayBitFlip(A() As Long, ByVal N As Long)
      Dim Element As Integer
        Element = N \ 32 + LBound(A)
        If Element <= UBound(A) And N >= 0 Then
          BitFlip A(Element), N Mod 32
        End If
      End Sub

      Function ArrayBitTest(A() As Long, ByVal N As Long) As Boolean
      ' Returns False if invalid N.
      Dim Element As Integer
        Element = N \ 32 + LBound(A)
        If Element <= UBound(A) And N >= 0 Then
          ArrayBitTest = BitTest(A(Element), N Mod 32)
        Else
          ArrayBitTest = False
        End If
      End Function

2. You can the use the functions in code as follows. Add the following code
   to the module:

      Sub Main()
         Dim Bits As Long, aBits(0 To 2) As Long
         Bits = &H8000C000&
         BitSet Bits, 5, True
         BitSet Bits, 15, False
         ArrayBitSet aBits(), 45, True
         Debug.Print Hex$(Bits), BitTest(Bits, 4)
         Debug.Print Hex$(aBits(0)), Hex$(aBits(1)), Hex$(aBits(2))
      End Sub

3. Run the procedure "Main".

   RESULTS: The debug window displays the following data.

      80004020      FALSE
      0      2000      0

REFERENCES

For more information about getting help with Visual Basic for Applications, please see the following article in the Microsoft Knowledge Base:

   ARTICLE-ID: Q163435
   TITLE     : VBA: Programming Resources for Visual Basic for
               Applications

(c) Microsoft Corporation 1998, All Rights Reserved. Contributions by Malcolm Stewart, Microsoft Corporation

Additional query words: vba kbVBA kbVBp kbDSupport kbDSD

Keywords          :  
Version           : WINDOWS:5.0
Platform          : WINDOWS
Issue type        : kbhowto kbinfo

Last Reviewed: May 19, 1999