'先理解下变量的地址与指向这个地址的值。xx省xx市xx街xx号就是一个地址,
'指向这个地址的值就是这个地址就有什么。比如这个地址是张三家的地址, '张三的家有什么呢?这个有什么就是这个地址所指向的值。
'VB没用操作指针的语言特性,因此需要通过WinAPI函数来进行操作,下面我们将
'演示一个非常简单的指针操作,让大家在VB使用指针有个基本的了解。 'CopyMemory函数参数 'CopyMemory是WinAPI函数,为了演示我把其修改成了两个版本, '版本1:CopyMemory1 '版本2:CopyMemory2 '版本1Destination及Source的参数是按照引用传递的(ByRef) '版本2Destination及Source的参数是按照值传递的(ByVal) '参数说明: 'Destination '要复制内存块的目的地址? 'Source '要复制内存块的源地址? 'Length '指定要复制内存块的大小,单位为字节 '返回值 '该函数为VOID型,没有返回值。 PrivateDeclareSubCopyMemory1Lib"kernel32"Alias"RtlMoveMemory"_ (ByRefDestinationAsAny,ByRefSourceAsAny,ByValLengthAsLong) PrivateDeclareSubCopyMemory2Lib"kernel32"Alias"RtlMoveMemory"_ (ByValDestinationAsAny,ByValSourceAsAny,ByValLengthAsLong) '在Basic语言演变成QBasic,然后到Visual Basic之前,VarPtr函数就已经存在了。 '开始,这个函数存在于VB运行库1.0版中。VarPtr函数的作用获取变量的地址 PrivateSubForm_Click() Dimlong1AsLong Dimlong2AsLong long1 =10 '版本1的CopyMemory CopyMemory1 long2,long1,4 MsgBoxlong2 '版本2的CopyMemory Dimlong3AsLong CopyMemory2 VarPtr(long3),VarPtr(long1),4 MsgBoxlong3 End Sub
-----------------------------------------------------
VB指针教程2
'我们先理解一下数组的概念,数组是由一组连续的内存区域构成
'比如有一排连续的房间,每个房间都有一个编号,这个编号也是连续的。 '例如房间1、房间2、...房间n,这个n就是房间的编号,如果我对你说“请”到房间2 '拿一本书给我,那么你完成这个任务首先就是找到房间2,然后进入房间2拿到这本书。 '显而易见这个编号实际上就是地址 '那么,如果我们取得数组的首地址,那么我们就可以根据地址对数组进行各种操作。 'C语言提供了取得数组地址的语言特性,而VB则没有这样的语言特性,但我们依然可以 '通过API得到数组的地址。我们先来认识下这一个DLL--Msvbvm60.dll,这个是vb6.0 '的程序运行库,其就提供了一个可以获得数组地址的API,它的api声明如下: PrivateDeclareFunctionVarPtrArrayLib"msvbvm60.dll"Alias"VarPtr"_ (ptr()AsAny)AsLong 'CopyMemory API请参照《VB指针教程1》,地址:http://bbs.bccn.net/thread-305122-1-1.html PrivateDeclareSubCopyMemoryLib"kernel32"Alias"RtlMoveMemory"_ (DestinationAsAny,SourceAsAny,ByValLengthAsLong) PrivateSubForm_Load() Dimarr(1To3)AsInteger Fori =1To3 arr(i) = i *10 Next DimarraddrAsLong '取得arr数组的首地址 arraddr = VarPtrArray(arr) Dimarr1AsInteger,arr2AsInteger,arr3AsInteger CopyMemory arr1,ByValarraddr,2 CopyMemory arr2,ByValarraddr +2,2 CopyMemory arr3,ByValarraddr +4,2 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_RECORDAs 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_UNKNOWNAs Integer = &H200 'IUnknown* 数组 'Private Const FADF_DISPATCH As Integer = &H400 'IDispatch* 数组 'Private Const FADF_VARIANTAs Integer = &H800 'VARIANTs数组 'Private Const FADF_RESERVEDAs Integer = &HF008 '余留,将来使用 PrivateSubCommand1_Click() List2.Clear List3.Clear Dimarr(1To3)AsInteger Fori =1To3 arr(i) = i *10 Next '指向SafeArrayld结构的指针 DimSafeArrayldPointAsLong '把arr数组的首地址复制到SafeArrayldPoint CopyMemory SafeArrayldPoint,ByValVarPtrArray(arr),4 '数组的维数 DimdimsAsInteger CopyMemory dims,ByValSafeArrayldPoint,2 List2.AddItem"数组的维数:"& dims DimelementsAsLong CopyMemory elements,ByValSafeArrayldPoint +4,4 List2.AddItem"数组元素所占的字节数:"& elements DimeCountAsLong CopyMemory eCount,ByValSafeArrayldPoint +16,4 List2.AddItem"数组元素的个数:"& eCount DimlBdAsLong CopyMemory lBd,ByValSafeArrayldPoint +20,4 List2.AddItem"数组的下限:"& lBd '读取数组的值 DimarraddrAsLong CopyMemory arraddr,ByValSafeArrayldPoint +12,4 Dimarr1AsInteger,arr3AsInteger CopyMemory arr1,2 CopyMemory arr2,2 CopyMemory arr3,2 List3.AddItem"arr(1)="& arr1 List3.AddItem"arr(2)="& arr2 List3.AddItem"arr(3)="& arr3 '修改数组的值 CopyMemoryByValarraddr,13,2 CopyMemoryByValarraddr +2,28,2 MsgBox"arr(1)="& arr(1) MsgBox"arr(2)="& arr(2) MsgBox"arr(3)="& arr(3) End Sub
------------------------------------------------------------
VB指针教程3
'如果遇到不会的知识点请参考上面的教程 '这一节我们来探讨下VB的字符串及字符串指针。 'VB的字符串类型其实是BSTR类型,是"Basic STRing"的简称,微软在COM/OLE中定义的标准字符串数据类型。 'BSTR类型的结构如下 PrivateType S_String WordLenAsLong'存放字符串的字节数 pData()AsInteger'存放指向字符串的指针(即地址) WordEndAsInteger'存放结束字符(即chr(0)) EndType PrivateDeclareSubCopyMemoryLib"kernel32"Alias"RtlMoveMemory"(DestinationAsAny,ByValLengthAsLong) '字符串在VB中的存储结构如下 PrivateSubForm_Click() 'StrPtr函数:返回真正的UNICODE字符串缓冲区的地址 DimstrAsString str="any string" DimiAsLong Print"VarPtr(str)="& VarPtr(str) &"字符串变量的地址" Print"StrPrt(str)="& StrPtr(str) &"字符串的地址" CopyMemory i,ByValVarPtr(str),4 Print"i="& i &"是字符串变量的地址所指向的值,它的值刚好是字符串的地址。" Print"从运行结果可以看出字符串变量的地址 VarPtr(str) 与字符串地址 StrPtr(str) 的区别。" Print"就是说字符串变量的地址VarPtr(str)存放着一个地址,这个地址就是字符串的地址,等价于StrPtr(str)" Print"那么我们就很容易理解为什么利用CopyMemory函数复制一个字符串到另一个字符串变量时参数是按值传递的" Print"读者可能会觉得奇怪,按值传递不就是把字符串传入去?CopyMemoy参数不是要求我们传递地址入去吗?" Print"没错,但不要忘记字符串的本质就是一个指针,指针就是地址。" Dims2AsString s2 =String$(Len(str),0) CopyMemoryByVals2,ByValstr,Len(str) Print"s2="& s2 DimstrLenAsLong CopyMemory strLen,ByValStrPtr(str) -4,4 Print"strLen="& strLen;"这是字符串的字节数" Print"从结果可以看出是与字符串的存储结构对应的" Print"利用这个性质,我们以模拟一下LenB函数和Len函数,分别为MyLenB、MyLen" Print"MyLenB(str)="& MyLenB(str) Print"MyLen(str)="& MyLen(str) Print"我们现在验证一下字符串存储结构中的WordEnd所存的是不是一个结束字符chr(0)" DimweAsInteger CopyMemory wn,ByValStrPtr(str) + LenB(str),2 Print"we="& we End Sub PrivateFunctionMyLenB(strAsString)AsLong CopyMemory MyLenB,4 End Function PrivateFunctionMyLen(strAsString)AsLong CopyMemory MyLen,4 MyLen = MyLen /2 End Function |