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?
Printable View
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?
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.
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
Here's the standard way to get HI and LO WORD:
And HI LO BYTE: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
You'll need it sooner or later if you use the API much.Code:' This is the LOBYTE of the wParam:
LOBYTE = wParam And &HFF&
' This is the HIBYTE of the wParam:
HIBYTE = wParam \ &H100 And &HFF&
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
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?
Any ideas about byte arrays and strings?
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.
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
To bit shift, use TheOnly's code. Yes it will overflow ifCode: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
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
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:
README.TXT 's ID should be 8882CFF1 in hexCode: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;
}
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 :)
Okay, it changes text to italic when there's "I" between "[" and "]". So there should be name"I".
Hope you got this :)
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.:D
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
Sorry, thanks for the note! That was old VB 3 junk I picked off the web from MSDN a while ago! :rolleyes:
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: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
Thanks to the others who posted alternate methods - interesting.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))
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.
The very very bestest best ways to use all the bit stuff, no overflows, no errors, no nothing except working code:
Usages: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
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)