65.9K
CodeProject 正在变化。 阅读更多。
Home

如何在 Visual Basic 中使用指针

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.83/5 (23投票s)

2000 年 9 月 4 日

viewsIcon

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

奖励

这是一个简单且不完整的链表实现。(在窗体上放置一个名为 Command1Command 按钮)

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
© . All rights reserved.