Introduction
Most people think that Visual Basic does not have pointers and hence is not capable of handling data structures that require pointers (by the way these data structures can be implemented using classes).
Well, they are right but not for very long. Since Visual Basic has access to the entire Win32 API it is not so difficult to equip it with pointers. Let's look at a simple code fragment in C and then at its Visual Basic equivalent.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{
int * ptr;
ptr=(int *)malloc(sizeof(int));
*ptr=10;
printf("The address of ptr is %d and its values is %d\n",ptr,*ptr);
free(ptr);
return 0;
}
I have marked the lines with numbers so you ,the reader, can follow more easily.
The equivalent of the first line, in VB is:
dim ptr as long
This was easy because it follows from the definition of the pointer. A pointer is just a variable whose value is the address of another variable. It is long
because a pointer in MS Windows is 4 bytes.
The second line:
ptr=(int *)malloc(sizeof(int));
Well, how do we allocate memory dynamically in Visual Basic? malloc
has no equivalent. Here we'll use the Win32 API function HeapAlloc(...)
.Please check the documentation for more information on it.
So here's our code:
Dim hHeap As Long hHeap = GetProcessHeap()
ptr=HeapAlloc(hHeap,0,2)
We can even check if memory was allocated.
if ptr<>0 then
end if
Now,
*ptr=10;
In Visual Basic we'll use the function CopyMemory
which is declared like so:
Public Declare Sub CopyMemory Lib "kernel32" Alias _
"RtlMoveMemory" (Destination As Any, Source As Any, _
ByVal Length As Long)
Here's the little trick : I modify the parameters and have two more definitions.
Public Declare Sub CopyMemoryWrite Lib "kernel32" Alias _
"RtlMoveMemory" (Byval Destination As long, Source As Any, _
ByVal Length As Long)
Public Declare Sub CopyMemoryRead Lib "kernel32" Alias _
"RtlMoveMemory" (Destination As Any,byval Source As Long, _
ByVal Length As Long)
Now here's how,
*ptr=10;
translates into Visual Basic.
dim i as integer
i=10
CopyMemoryWrite ptr,i,2
Now towards line 5.
dim j as integer
CopyMemoryRead j,ptr,2
MsgBox "The adress of ptr is " & cstr(ptr) & _
vbCrlf & "and the value is " & cstr(j)
Now free the memory
HeapFree GetProcessHeap(),0,ptr
Here is the complete listing of the source code: (just copy it into a project and run it).
Option Explicit
Private Declare Sub CopyMemory Lib "kernel32" _
Alias "RtlMoveMemory" (Destination As Any, _
Source As Any, ByVal Length As Long)
Private Declare Function GetProcessHeap Lib "kernel32" () As Long
Private Declare Function HeapAlloc Lib "kernel32" _
(ByVal hHeap As Long, ByVal dwFlags As Long,_
ByVal dwBytes As Long) As Long
Private Declare Function HeapFree Lib "kernel32" _
(ByVal hHeap As Long, ByVal dwFlags As Long, lpMem As Any) As Long
Private Declare Sub CopyMemoryWrite Lib "kernel32" Alias _
"RtlMoveMemory" (ByVal Destination As Long, _
Source As Any, ByVal Length As Long)
Private Declare Sub CopyMemoryRead Lib "kernel32" Alias _
"RtlMoveMemory" (Destination As Any, _
ByVal Source As Long, ByVal Length As Long)
Private Sub Form_Load()
Dim ptr As Long
Dim hHeap As Long
hHeap = GetProcessHeap()
ptr = HeapAlloc(hHeap, 0, 2)
If ptr <> 0 Then
Dim i As Integer
i = 10
CopyMemoryWrite ptr, i, 2
Dim j As Integer
CopyMemoryRead j, ptr, 2
MsgBox "The adress of ptr is " & CStr(ptr) & _
vbCrLf & "and the value is " & CStr(j)
HeapFree GetProcessHeap(), 0, ptr
End If
End Sub
Bonus
Here is a simple and not complete implementation of a linked list. (On the form put a Command
button named Command1
)
Option Explicit
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory"_
(Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Function GetProcessHeap Lib "kernel32" () As Long
Private Declare Function HeapAlloc Lib "kernel32" _
(ByVal hHeap As Long, ByVal dwFlags As Long, _
ByVal dwBytes As Long) As Long
Private Declare Function HeapFree Lib "kernel32" _
(ByVal hHeap As Long, ByVal dwFlags As Long, _
lpMem As Any) As Long
Private Declare Sub CopyMemoryPut Lib "kernel32" Alias _
"RtlMoveMemory" (ByVal Destination As Long, _
Source As Any, ByVal Length As Long)
Private Declare Sub CopyMemoryRead Lib "kernel32" Alias _
"RtlMoveMemory" (Destination As Any, _
ByVal Source As Long, ByVal Length As Long)
Dim pHead As Long
Private Type ListElement
strData As String * 255
pNext As Long
End Type
Private Sub CreateLinkedList()
Dim pFirst As Long, pSecond As Long
Dim hHeap As Long
hHeap = GetProcessHeap()
pFirst = HeapAlloc(hHeap, 0, 504)
pSecond = HeapAlloc(hHeap, 0, 504)
If pFirst <> 0 And pSecond <> 0 Then
PutDataIntoStructure pFirst, "Hello", pSecond
PutDataIntoStructure pSecond, "Pointers", 0
pHead = pFirst
End If
End Sub
Private Sub Command1_Click()
CreateLinkedList
ReadLinkedListDataAndFreeMemory
End Sub
Private Sub PutDataIntoStructure(ByVal ptr As Long, _
szdata As String, ByVal ptrNext As Long)
Dim le As ListElement
le.strData = szdata
le.pNext = ptrNext
CopyMemoryPut ptr, le, 504
End Sub
Private Sub ReadDataToStructure(ByVal ptr As Long, _
struct As ListElement)
Dim le As ListElement
CopyMemoryRead le, ptr, 504
struct.strData = le.strData
struct.pNext = le.pNext
End Sub
Private Sub ReadLinkedListDataAndFreeMemory()
Dim pLocal As Long
Dim hHeap As Long
Dim le As ListElement
Dim strData As String
pLocal = pHead
hHeap = GetProcessHeap()
Do While pLocal <> 0
ReadDataToStructure pLocal, le
strData = strData & vbCrLf & le.strData
HeapFree hHeap, 0, pLocal
pLocal = le.pNext
Loop
MsgBox strData
End Sub
Private Sub Form_Load()
End Sub