如何在 Visual Basic 中使用指针






4.83/5 (23投票s)
2000 年 9 月 4 日

495118
展示如何在 C 语言中像使用指针一样使用指针
引言
大多数人认为 Visual Basic 没有指针,因此无法处理需要指针的数据结构(顺便说一下,这些数据结构可以使用类来实现)。
他们说得没错,但不会持续太久。由于 Visual Basic 可以访问整个 Win32 API,因此配备指针并不困难。让我们看一个 C 语言中的简单代码片段,然后是它的 Visual Basic 等效代码。
#include <stdio.h> #include <stdlib.h> int main(int argc, char* argv[]) { int * ptr; //1 ptr=(int *)malloc(sizeof(int)); //2 *ptr=10; //3 printf("The address of ptr is %d and its values is %d\n",ptr,*ptr); //4 free(ptr); //5 return 0; }
我用数字标记了行,以便读者更容易理解。
VB 中的第一行等效于
dim ptr as long 'int * ptr;
这很简单,因为它遵循指针的定义。指针只是一个变量,其值为另一个变量的地址。它使用 long
,因为 MS Windows 中的指针是 4 字节。
第二行
ptr=(int *)malloc(sizeof(int));
那么,如何在 Visual Basic 中动态分配内存?malloc
没有等效函数。在这里,我们将使用 Win32 API 函数 HeapAlloc(...)
。请查阅文档以获取更多信息。
这是我们的代码
Dim hHeap As Long hHeap = GetProcessHeap()
ptr=HeapAlloc(hHeap,0,2) 'an integer in Visual Basic is 2 bytes
我们甚至可以检查是否已分配内存。
if ptr<>0 then
'memory was allocated
'do stuff
end if
现在,
*ptr=10;
在 Visual Basic 中,我们将使用函数 CopyMemory
,其声明如下
Public Declare Sub CopyMemory Lib "kernel32" Alias _
"RtlMoveMemory" (Destination As Any, Source As Any, _
ByVal Length As Long)
这里有一个小技巧:我修改了参数并添加了两个定义。
'to write to memory
Public Declare Sub CopyMemoryWrite Lib "kernel32" Alias _
"RtlMoveMemory" (Byval Destination As long, Source As Any, _
ByVal Length As Long)
' to read from memory
Public Declare Sub CopyMemoryRead Lib "kernel32" Alias _
"RtlMoveMemory" (Destination As Any,byval Source As Long, _
ByVal Length As Long)
现在,
*ptr=10;
转换为 Visual Basic。
dim i as integer
i=10
CopyMemoryWrite ptr,i,2 ' an intger is two bytes
现在转向第 5 行。
'printf("%d\n",*ptr);
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
这是源代码的完整列表:(只需将其复制到项目中并运行即可)。
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 'int * ptr;
Dim hHeap As Long
hHeap = GetProcessHeap()
ptr = HeapAlloc(hHeap, 0, 2) 'an integer in Visual Basic is 2 bytes
If ptr <> 0 Then
'memory was allocated
'do stuff
Dim i As Integer
i = 10
CopyMemoryWrite ptr, i, 2 ' an intger is two bytes
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
奖励
这是一个简单且不完整的链表实现。(在窗体上放置一个名为 Command1
的 Command
按钮)
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 '==255 * 2=500 bytes vbStrings are UNICODE !
pNext As Long '4 bytes
'pointer to next ; ==0 if end of list
'----------------
'total: 504 bytes
End Type
Private Sub CreateLinkedList()
'add three items to list
' get the heap first
Dim pFirst As Long, pSecond As Long 'local pointers
Dim hHeap As Long
hHeap = GetProcessHeap()
'allocate memory for the first and second element
pFirst = HeapAlloc(hHeap, 0, 504)
pSecond = HeapAlloc(hHeap, 0, 504)
If pFirst <> 0 And pSecond <> 0 Then
'memory is allocated
PutDataIntoStructure pFirst, "Hello", pSecond
PutDataIntoStructure pSecond, "Pointers", 0
pHead = pFirst
End If
'put he second element in the list
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