Results 1 to 15 of 15

Thread: Bit shifting in VB...

  1. #1
    Guest
    How can I do bit shifting in VB? Is there any other way than to change value hard way to binary and then do the shifting and after all convert final value to desimal?

  2. #2
    Lively Member
    Join Date
    May 2000
    Location
    Norway
    Posts
    112

    Unhappy

    Don't think there is any easy way doing that.
    Working with bits in VB is hard. Just try to split an integer(WORD) into its High and Low values. &HEFCD -> High=&HEF Low=&HCD.


  3. #3
    Addicted Member
    Join Date
    Oct 2000
    Location
    Vienna/Austria
    Posts
    132

    Wink

    Hi !!!

    I can't remember where I found the information about left/right shifting in VB (Microsoft or Net ?)

    But here is the code:

    Private Function Shl(ByVal dw As Long, n As Byte) As Long
    Shl = dw * 2 ^ n
    End Function

    Private Function Shr(dw As Long, n As Byte) As Long
    Shr = dw \ 2 ^ n
    End Function


    hope this help

  4. #4
    Lively Member
    Join Date
    Aug 2000
    Location
    quebec
    Posts
    81

    Cool

    Here's the standard way to get HI and LO WORD:

    Code:
    Public Function GetHiWord(dw As Long) As Integer
        If dw And &H80000000 Then
            GetHiWord = (dw \ &HFFFF) - 1
        Else
            GetHiWord = dw \ &HFFFF
        End If
    End Function
    
    
    Public Function GetLoWord(dw As Long) As Integer
        If dw And &H8000 Then
          GetLoWord = &H8000 Or (dw And &H7FFF& )
        Else
          GetLoWord = dw And &HFFF&
        End If
    End Function
    And HI LO BYTE:
    Code:
    ' This is the LOBYTE of the wParam:
       LOBYTE = wParam And &HFF&
       ' This is the HIBYTE of the wParam:
       HIBYTE = wParam \ &H100 And &HFF&
    You'll need it sooner or later if you use the API much.
    C/C++,Delphi,VB6,Java,PB (blech!),ASP,JSP,SQL...bla bla bla and bla
    I love deadlines. I like the whooshing sound they make as they fly by.
    óDouglas Adams

  5. #5
    Frenzied Member
    Join Date
    Aug 2000
    Location
    O!
    Posts
    1,177
    Here is an alternate method with examples for both Integers and Longs.

    Code:
    Private Declare Sub CopyMemory Lib "KERNEL32" _
                Alias "RtlMoveMemory" (hpvDest As Any, _
                                       hpvSource As Any, _
                                       ByVal cbCopy As Long)
    
    Function HiWord(ByVal dw As Long) As Integer
        CopyMemory HiWord, ByVal VarPtr(dw) + 2, 2
    End Function
    
    Function LoWord(ByVal dw As Long) As Integer
        CopyMemory LoWord, dw, 2
    End Function
    
    Function HiByte(ByVal w As Integer) As Byte
        CopyMemory HiByte, ByVal VarPtr(w) + 1, 1
    End Function
    
    Function LoByte(ByVal w As Integer) Byte
        CopyMemory LoByte, w, 1
    End Function

  6. #6
    Frenzied Member HarryW's Avatar
    Join Date
    Jan 2000
    Location
    Heiho no michi
    Posts
    1,827
    Using this quoted function:

    Private Function Shl(ByVal dw As Long, n As Byte) As Long
    Shl = dw * 2 ^ n
    End Function

    wouldn't you have problems with overflows?
    Harry.

    "From one thing, know ten thousand things."

  7. #7
    old fart Frans C's Avatar
    Join Date
    Oct 1999
    Location
    the Netherlands
    Posts
    2,926
    Any ideas about byte arrays and strings?

  8. #8
    Frenzied Member
    Join Date
    Aug 2000
    Location
    O!
    Posts
    1,177
    What do you want to know "about byte arrays and strings"?

    This thread has gone from bit shifting to byte swapping to byte arrays and strings. No criticism intended, but perhaps your question should be in a new thread so that the right people see it.

  9. #9
    Hyperactive Member
    Join Date
    Jun 2000
    Location
    Auckland, NZ
    Posts
    411

    Hmmm..

    hitcgar, Do you stand by your suggestion? I seem to make
    it overflow quite easily by testing with a value like
    123456&.

    TheOnly answered the question properly because the question
    was about shifting bits left or right.

    All the replies that kindly tell MerryVIP how to split
    words into integers (the ones that work) are very nice, but
    don't really answer the question...

    As for my 5 cents worth:
    To Split a Word, use the UDT
    Code:
    Private Type SplitLong
      lo As Integer
      hi As Integer
    End Type
      
    Private Type NormalLong
      val As Long
    End Type
    
    ' in some sub 
      Dim myLong1 As SplitLong
      Dim myLong2 As NormalLong
      myLong2.val = 123456&
      
      LSet myLong1 = myLong2
      Debug.Print myLong1.hi, myLong1.lo
    To bit shift, use TheOnly's code. Yes it will overflow if
    you put in a high value for n, however you can either limit
    n in the function or assume the user knows what the heck
    they're doing. Who would even want to try to bit shift
    beyond a word boundary anyhow?

    If you don't know what bit shifting is, then here is a clue
    If you bit shift the number 3 by 2 bits to the left, you
    get 12. If you bit shift 10, by 1 bit to the right, you
    get 5. Clear as mud?

    Cheers

    Paul Lewis

  10. #10
    Guest

    Overflows...:(

    Okay, where I need the bit shifting is a C/C++ code I've to translate to VB (I've only DJGPP C/C++ compiler which is for DOS and I can't afford MS C++ etc.)

    The code calculates ID from a file name, like filename can be README.TXT - I need the ID calculating for my game editor.

    Here's the code:

    Code:
    int Cmix_file::get_id(string name)
    {
        name = to_upper(name);
        int i = 0;
        unsigned int id = 0;
        int l = name.length();
        while (i < l)
        {
            unsigned int a = 0;
            for (int j = 0; j < 4; j++)
            {
                a >>= 8;
                if (i < l)
                    a += static_cast<unsigned int>(name[i]) << 24;
                i++;
            }
            id = (id << 1 | id >> 31) + a;
        }
        return id;
    }
    README.TXT 's ID should be 8882CFF1 in hex
    and hmm...README.DOC returns the same so it looks like it
    takes only README. But that can't be like that...Or can it?
    Well, have to search the things little more.

    Thanks for the replies

  11. #11
    Guest

    Fix...

    Okay, it changes text to italic when there's "I" between "[" and "]". So there should be name"I".

    Hope you got this

  12. #12
    old fart Frans C's Avatar
    Join Date
    Oct 1999
    Location
    the Netherlands
    Posts
    2,926
    OK, maybe I didn't make myself clear enough.
    The only solutions for bit shifting given so far, worked on integers and long's. How should I go around when I wanted a bit shift on a block of memory bigger then these, like a string or byte array (or an allocated block of memory created with the GlobalAlloc API, or a bitmap, or whatever)?

    If nobody knows the answer, never mind. It was only a hypothetical question.

  13. #13
    Hyperactive Member
    Join Date
    Jun 2000
    Location
    Auckland, NZ
    Posts
    411

    Even hypothetically

    The idea of bit shifting outside of a word boundary is foreign to me. Perhaps my lack of C++ experience is showing through?

    When do you ever want to bit shift across a byte array or string? And how do you do this in C++.

    My guess is that you need to use a loop to achieve it. Afterall, the << and >> operators in C++ only work on Integers anyhow.

    Cheers
    Paul Lewis

  14. #14
    Lively Member
    Join Date
    Aug 2000
    Location
    quebec
    Posts
    81

    Arrow

    Sorry, thanks for the note! That was old VB 3 junk I picked off the web from MSDN a while ago!
    Code:
    Public  Function LoWord(DWord As Long) As Integer
          If DWord And &H8000& Then ' &H8000& = &H00008000
             LoWord = DWord Or &HFFFF0000
          Else
             LoWord = DWord And &HFFFF&
          End If
    End Function
    
    Public Function HiWord(DWord As Long) As Integer
          HiWord = (DWord And &HFFFF0000) \ &H10000
    End Function
    
    Public Function MakeDWord(LoWord As Integer, HiWord As Integer) As Long
          MakeDWord = (HiWord * &H10000) Or (LoWord And &HFFFF&)
       End Function
    Hi & Lo word extracting is usally done with bit shifting or bitwise ANDing as you can see from the definitions of the HIWORD, LOWORD macros in C:
    Code:
    #define LOWORD(l)  ((WORD)((DWORD_PTR)(l) & 0xffff))
    #define HIWORD(l)  ((WORD)((DWORD_PTR)(l) >> 16))
    #define LOBYTE(w)  ((BYTE)((DWORD_PTR)(w) & 0xff))
    #define HIBYTE(w)  ((BYTE)((DWORD_PTR)(w) >> 8))
    Thanks to the others who posted alternate methods - interesting.

    You can use TheOnly's posted code to do the shift right 16 to extract the HIWORD or shift right 8 for the HIBYTE.

    Anyway doesn't solve original question.
    C/C++,Delphi,VB6,Java,PB (blech!),ASP,JSP,SQL...bla bla bla and bla
    I love deadlines. I like the whooshing sound they make as they fly by.
    óDouglas Adams

  15. #15
    Guru Yonatan's Avatar
    Join Date
    Apr 1999
    Location
    Israel
    Posts
    892
    The very very bestest best ways to use all the bit stuff, no overflows, no errors, no nothing except working code:
    Code:
    Option Explicit
    
    Function RShift(ByVal lNum As Long, ByVal lBits As Long) As Long
        If lBits <= 0 Then RShift = lNum
        If (lBits <= 0) Or (lBits > 31) Then Exit Function
        
        RShift = (lNum And (2 ^ (31 - lBits) - 1)) * _
            IIf(lBits = 31, &H80000000, 2 ^ lBits) Or _
            IIf((lNum And 2 ^ (31 - lBits)) = 2 ^ (31 - lBits), _
            &H80000000, 0)
    End Function
    
    Function LShift(ByVal lNum As Long, ByVal lBits As Long) As Long
        If lBits <= 0 Then LShift = lNum
        If (lBits <= 0) Or (lBits > 31) Then Exit Function
        
        If lNum < 0 Then
            LShift = (lNum And &H7FFFFFFF) \ (2 ^ lBits) Or 2 ^ (31 - lBits)
        Else
            LShift = lNum \ (2 ^ lBits)
        End If
    End Function
    
    Property Get LoWord(dwNum As Long) As Integer
        LoWord = dwNum And &HFFFF
    End Property
    
    Property Let LoWord(dwNum As Long, ByVal wNewWord As Integer)
        dwNum = dwNum And &HFFFF0000 Or wNewWord
    End Property
    
    Property Get HiWord(dwNum As Long) As Integer
        HiWord = ((dwNum And IIf(dwNum < 0, &H7FFF0000, &HFFFF0000)) \ _
            &H10000) Or (-(dwNum < 0) * &H8000)
    End Property
    
    Property Let HiWord(dwNum As Long, ByVal wNewWord As Integer)
        dwNum = dwNum And &HFFFF& Or IIf(wNewWord < 0, ((wNewWord And &H7FFF) _
            * &H10000) Or &H80000000, wNewWord * &H10000)
    End Property
    
    Property Get LoByte(wNum As Integer) As Byte
        LoByte = wNum And &HFF
    End Property
    
    Property Let LoByte(wNum As Integer, ByVal btNewByte As Byte)
        wNum = wNum And &HFF00 Or btNewByte
    End Property
    
    Property Get HiByte(wNum As Integer) As Byte
        HiByte = (wNum And &HFF00&) \ &H100
    End Property
    
    Property Let HiByte(wNum As Integer, ByVal btNewByte As Byte)
        wNum = wNum And &HFF Or (btNewByte * &H100&)
    End Property
    Usages:
    Code:
    Something = RShift(SomeValue, HowManyBits) ' Same with LShift
    
    MyWord = HiWord(MyDWord) ' Get the HiWord (same way with LoWord)
    HiWord(MyDWord) = MyWord ' Set the HiWord (same with LoWord)
    
    MyByte = HiByte(MyWord) ' Get the HiByte (same with LoByte)
    HiByte(MyWord) = MyByte ' Set the HiByte (same with LoByte)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width