标题: VB6拾遗:虚幻的指针
作者: Demon
链接: https://demon.tw/programming/vb6-repick-phantom-pointers.html
版权: 本博客的所有文章,都遵守“署名-非商业性使用-相同方式共享 2.5 中国大陆”协议条款。
指针似乎是C/C++的代名词,其实VB中也有指针。
在VB中不允许定义指针类型的变量,也没有内建的用地址对内存进行操作的方法,所以从某种意义上来说,VB是没有指针的。
到底有没有指针,关键看如何理解指针这个概念,《C程序设计语言》一书中是这样定义的:指针是能够存放一个地址的一组存储单元(通常是2个或4个字节)。所以如果我们能在VB中定义一个变量,该变量存放的是一个内存地址,那么我们可以认为这就是指针。
VB中有三种指针。第一种是变量的内存地址,第二种是字符串、对象、数组的地址(这些变量有两个指针:一个是变量的,一个是数据的),第三种是函数指针。每种指针获取的方式都不尽相同。
可以使用VarPtr函数来获取任意非数组变量的地址,相当于C语言中的地址运算符&:
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _ (ByVal Destination As Any, ByVal Source As Any, ByVal Length As Long) Sub Main() Dim n1 As Long Dim n2 As Long n1 = 123456 CopyMemory VarPtr(n2), VarPtr(n1), 4 Debug.Print n2 End Sub
可以用StrPtr函数来获取指向字符串变量中字符串数据的指针,与VarPtr不同,StrPtr获取的是指向实际数据的指针,而不是指向变量本身的指针:
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _ (ByVal Destination As Any, ByVal Source As Any, ByVal Length As Long) Sub Main() Dim s1 As String Dim s2 As String s1 = "https://demon.tw" s2 = String$(Len(s1), 0) CopyMemory StrPtr(s2), StrPtr(s1), LenB(s1) Debug.Print s2 End Sub
用VarPtr也可以实现相同的效果,只不过比较麻烦:
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _ (ByVal Destination As Any, ByVal Source As Any, ByVal Length As Long) Sub Main() Dim s1 As String, s2 As String Dim p1 As Long, p2 As Long s1 = "https://demon.tw" s2 = String$(Len(s1), 0) CopyMemory VarPtr(p1), VarPtr(s1), 4 CopyMemory VarPtr(p2), VarPtr(s2), 4 CopyMemory p2, p1, LenB(s1) Debug.Print s2 End Sub
而ObjPtr函数可以获取指向对象的指针:
Sub Main() Dim o1 As Object, o2 As Object Set o1 = New Collection Set o2 = o1 Debug.Print VarPtr(o1); VarPtr(o2) Debug.Print ObjPtr(o1); ObjPtr(o2) End Sub
最后,可以使用VB的AddressOf操作符来获取标准模块(.bas)中任意函数的地址,AddressOf最初是设计用来为Win32 API提供回调函数的:
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _ (ByVal Destination As Any, ByVal Source As Any, ByVal Length As Long) Public Declare Function EnumSystemCodePages Lib "kernel32" Alias "EnumSystemCodePagesW" _ (ByVal lpCodePageEnumProc As Long, ByVal dwFlags As Long) As Long Const CP_INSTALLED = &H1& Function EnumCodePagesProc(ByVal lpCodePageString As Long) As Long Dim buffer As String buffer = String$(256, 0) CopyMemory StrPtr(buffer), lpCodePageString, LenB(buffer) buffer = Left$(buffer, InStr(buffer, vbNullChar) - 1) Debug.Print buffer EnumCodePagesProc = 1& End Function Sub Main() Call EnumSystemCodePages(AddressOf EnumCodePagesProc, CP_INSTALLED) End Sub
指针是把双刃剑,使用时一定要万分小心,不然很容易导致VB崩溃。
赞赏微信赞赏支付宝赞赏
随机文章:
太有用了 老实说前段时间我也在想这个 不过不是在VB上实现 是在VBS DX1.0上调用API函数时