打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
VB指针教程 (1, 2, 3)
VB指针教程1

'先理解下变量的地址与指向这个地址的值。xx省xx市xx街xx号就是一个地址,
'指向这个地址的值就是这个地址就有什么。比如这个地址是张三家的地址,
'张三的家有什么呢?这个有什么就是这个地址所指向的值。

'VB没用操作指针的语言特性,因此需要通过WinAPI函数来进行操作,下面我们将
'
演示一个非常简单的指针操作,让大家在VB使用指针有个基本的了解。
'
CopyMemory函数参数
'
CopyMemory是WinAPI函数,为了演示我把其修改成了两个版本,
'
版本1:CopyMemory1
'
版本2:CopyMemory2
'
版本1Destination及Source的参数是按照引用传递的(ByRef)
'
版本2Destination及Source的参数是按照值传递的(ByVal)
'
参数说明:
'
Destination
'
要复制内存块的目的地址?
'
Source
'
要复制内存块的源地址?
'
Length
'
指定要复制内存块的大小,单位为字节
'
返回值
'
该函数为VOID型,没有返回值。
Private Declare Sub CopyMemory1 Lib "kernel32" Alias "RtlMoveMemory" _
        (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)

Private Declare Sub CopyMemory2 Lib "kernel32" Alias "RtlMoveMemory" _
        (ByVal Destination As Any, ByVal Source As Any, ByVal Length As Long)

'在Basic语言演变成QBasic,然后到Visual Basic之前,VarPtr函数就已经存在了。
'
开始,这个函数存在于VB运行库1.0版中。VarPtr函数的作用获取变量的地址
Private Sub Form_Click()
    Dim long1 As Long
    Dim long2 As Long
    long1 = 10
    '版本1的CopyMemory
    CopyMemory1 long2, long1, 4
    MsgBox long2
    '版本2的CopyMemory
    Dim long3 As Long
    CopyMemory2 VarPtr(long3), VarPtr(long1), 4
    MsgBox long3
End Sub


-----------------------------------------------------



'我们先理解一下数组的概念,数组是由一组连续的内存区域构成
'
比如有一排连续的房间,每个房间都有一个编号,这个编号也是连续的。
'
例如房间1、房间2、...房间n,这个n就是房间的编号,如果我对你说“请”到房间2
'
拿一本书给我,那么你完成这个任务首先就是找到房间2,然后进入房间2拿到这本书。
'
显而易见这个编号实际上就是地址
'
那么,如果我们取得数组的首地址,那么我们就可以根据地址对数组进行各种操作。
'
C语言提供了取得数组地址的语言特性,而VB则没有这样的语言特性,但我们依然可以
'
通过API得到数组的地址。我们先来认识下这一个DLL--Msvbvm60.dll,这个是vb6.0
'
的程序运行库,其就提供了一个可以获得数组地址的API,它的api声明如下:
Private Declare Function VarPtrArray Lib "msvbvm60.dll" Alias "VarPtr" _
        (ptr() As Any) As Long
        
'CopyMemory API请参照《VB指针教程1》,地址:http://bbs.bccn.net/thread-305122-1-1.html
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
       (Destination As Any, Source As Any, ByVal Length As Long)

Private Sub Form_Load()
    Dim arr(1 To 3As Integer
    For i = 1 To 3
        arr(i) = i * 10
    Next
    Dim arraddr As Long
    '取得arr数组的首地址
    arraddr = VarPtrArray(arr)
    Dim arr1 As Integer, arr2 As Integer, arr3 As Integer
    CopyMemory arr1, ByVal arraddr, 2
    CopyMemory arr2, ByVal arraddr + 22
    CopyMemory arr3, ByVal arraddr + 42
    List1.AddItem "arr(1)=" & arr1
    List1.AddItem "arr(2)=" & arr2
    List1.AddItem "arr(3)=" & arr3
End Sub
'观察运行的结果,显然不是我们所预期的,为什么呢?这是因为VB数组的存储结构不同于我们先前所说的。
'
VB数组的存储结构是使用一种叫做SafeArray的结构,而VarPtrArray(arr)取得的即是指向SafeArray结
'
构的指针,我们现在得先去了解下SafeArray结构:
'
Private Type SafeArray
'
    cDims As Integer     '指向数组维数的指针
'
    fFeatures As Integer '用来描述数组如何分配和如何被释放的标志
'
    cbElements As Long   '指向数组元素所占的字节数的指针
'
    cLocks As Long       '一个计数器,用来跟踪该数组被锁定的次数
'
    pvData As Long       '指向数组内一个元素的指针,最重要的部分
'
    cElements As Long    '数组元素的个数
'
    lLbound As Long      '数组的下限
'
End Type
'
'以下是fFeatures的常量标志
'
Private Const FADF_AUTO         As Integer = &H1   '在堆栈中执行的分配
'
Private Const FADF_STATIC       As Integer = &H2   '静态分配
'
Private Const FADF_EMBEDDED     As Integer = &H4   '在结构中创建
'
Private Const FADF_FIXEDSIZE   As Integer = &H10   '不能改变数组大小
'
Private Const FADF_RECORD      As Integer = &H20   '记录容器
'
Private Const FADF_HAVEIID     As Integer = &H40   '有IID 身份标记 数组
'
Private Const FADF_HAVEVARTYPE As Integer = &H80   'VT 类型数组
'
Private Const FADF_BSTR       As Integer = &H100   'BSTR数组
'
Private Const FADF_UNKNOWN    As Integer = &H200   'IUnknown* 数组
'
Private Const FADF_DISPATCH   As Integer = &H400   'IDispatch* 数组
'
Private Const FADF_VARIANT    As Integer = &H800   'VARIANTs数组
'
Private Const FADF_RESERVED  As Integer = &HF008   '余留,将来使用

   
Private Sub Command1_Click()
   List2.Clear
   List3.Clear
   Dim arr(1 To 3As Integer
   For i = 1 To 3
       arr(i) = i * 10
   Next
   '指向SafeArrayld结构的指针
   Dim SafeArrayldPoint As Long
   
   '把arr数组的首地址复制到SafeArrayldPoint
   CopyMemory SafeArrayldPoint, ByVal VarPtrArray(arr), 4
   
   '数组的维数
   Dim dims As Integer
   CopyMemory dims, ByVal SafeArrayldPoint, 2
   List2.AddItem "数组的维数:" & dims
   
   Dim elements As Long
   CopyMemory elements, ByVal SafeArrayldPoint + 44
   List2.AddItem "数组元素所占的字节数:" & elements
   
   Dim eCount As Long
   CopyMemory eCount, ByVal SafeArrayldPoint + 164
   List2.AddItem "数组元素的个数:" & eCount
  
   Dim lBd As Long
   CopyMemory lBd, ByVal SafeArrayldPoint + 204
   List2.AddItem "数组的下限:" & lBd
    '读取数组的值
   Dim arraddr As Long
   CopyMemory arraddr, ByVal SafeArrayldPoint + 124
   Dim arr1 As Integer, arr2 As Integer, arr3 As Integer
   CopyMemory arr1, ByVal arraddr, 2
   CopyMemory arr2, ByVal arraddr + 22
   CopyMemory arr3, ByVal arraddr + 42
   List3.AddItem "arr(1)=" & arr1
   List3.AddItem "arr(2)=" & arr2
   List3.AddItem "arr(3)=" & arr3
   '修改数组的值
   CopyMemory ByVal arraddr, 132
   CopyMemory ByVal arraddr + 2282
   MsgBox "arr(1)=" & arr(1)
   MsgBox "arr(2)=" & arr(2)
   MsgBox "arr(3)=" & arr(3)
    
End Sub

------------------------------------------------------------


'如果遇到不会的知识点请参考上面的教程
'
这一节我们来探讨下VB的字符串及字符串指针。
'
VB的字符串类型其实是BSTR类型,是"Basic STRing"的简称,微软在COM/OLE中定义的标准字符串数据类型。
'
BSTR类型的结构如下
Private Type S_String
    WordLen As Long    '存放字符串的字节数
    pData() As Integer '存放指向字符串的指针(即地址)
    WordEnd As Integer '存放结束字符(即chr(0))
End Type

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)

'字符串在VB中的存储结构如下


Private Sub Form_Click()
    'StrPtr函数:返回真正的UNICODE字符串缓冲区的地址
    Dim str As String
    str = "any string"
    Dim i As Long
    Print "VarPtr(str)=" & VarPtr(str) & " 字符串变量的地址"
    Print "StrPrt(str)=" & StrPtr(str) & " 字符串的地址"
   
    CopyMemory i, ByVal VarPtr(str), 4
    Print "i=" & i & " 是字符串变量的地址所指向的值,它的值刚好是字符串的地址。"
    Print "从运行结果可以看出字符串变量的地址 VarPtr(str) 与字符串地址 StrPtr(str) 的区别。"
    Print "就是说字符串变量的地址VarPtr(str)存放着一个地址,这个地址就是字符串的地址,等价于StrPtr(str)"
    Print "那么我们就很容易理解为什么利用CopyMemory函数复制一个字符串到另一个字符串变量时参数是按值传递的"
    Print "读者可能会觉得奇怪,按值传递不就是把字符串传入去?CopyMemoy参数不是要求我们传递地址入去吗?"
    Print "没错,但不要忘记字符串的本质就是一个指针,指针就是地址。"
    Dim s2 As String
    s2 = String$(Len(str), 0)
    CopyMemory ByVal s2, ByVal strLen(str)
    Print "s2=" & s2
   
    Dim strLen As Long
    CopyMemory strLen, ByVal StrPtr(str) - 44
    Print "strLen=" & strLen; " 这是字符串的字节数"
    Print "从结果可以看出是与字符串的存储结构对应的"
    Print "利用这个性质,我们以模拟一下LenB函数和Len函数,分别为MyLenB、MyLen"
    Print "MyLenB(str)=" & MyLenB(str)
    Print "MyLen(str)=" & MyLen(str)
   
    Print "我们现在验证一下字符串存储结构中的WordEnd所存的是不是一个结束字符chr(0)"
    Dim we As Integer
    CopyMemory wn, ByVal StrPtr(str) + LenB(str), 2
    Print "we=" & we
End Sub

Private Function MyLenB(str As StringAs Long
     CopyMemory MyLenB, ByVal StrPtr(str) - 44
End Function

Private Function MyLen(str As StringAs Long
    CopyMemory MyLen, ByVal StrPtr(str) - 44
    MyLen = MyLen / 2
End Function
'如有谬误之处请各位指出,谢谢!
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
完善redim preserve语句功能
vb6.0 判断数组为空
在VB6中用CopyMemory拷贝字符串的种种猫腻(一)
2017
截取字符串方法总结(区分汉字、数字、字母)
VB6 通过winsock控件数组实现客户端和服务器多对一通信
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服