CopyMemory函数

来源:互联网 发布:小米笔记本软件模糊 编辑:程序博客网 时间:2024/05/17 02:37

CopyMemory函数

 

(1) VatPtr/ StrPtr/ ObjPtr

VarPtr:返回变量地址

StrPtr:返回真正的UNICODE字符串缓冲区的地址

ObjPtr:返回任何对象变量引用的地址

 

  它们是VB提供给我们的好宝贝,它们是VBA函数库中的隐藏函数。为什么要隐藏?因为VB开发小组,不鼓励我们用指针嘛。

  VarPtr返回的是变量所在处的内存地址,也可以说返回了指向变量内存位置的指针,它是我们在VB里处理指针最重要的武器之一。
 Private Declare Function ObjPtr Lib "MSVBVM60" Alias "VarPtr" (var As Object) As Long
 Private Declare Function VarPtr Lib "MSVBVM60" (var As Any) As Long

没有StrPtr,是因为VB对字符串处理方式有点不同,这方面的问题太多,

   

(2)  ByVal和ByRef

  ByVal传递的参数值,

  ByRef传递的参数的地址。我们不用去区别传指针/传地址/传引用的不同,在VB里,它们根本就是一个东西的三种不同说法,即使VB的文档里也有地方在混用这些术语(但在C++里的确要区分指针和引用)

  一定要搞清在里面的CopyMemory调用中,在什么地方要加ByVal,什么地方不加(不加ByVal就是使用VB缺省的ByRef),准确的理解传值和传地址(指针)的区别,是在VB里正确使用指针的基础。

 

(3)AddressOf

  它用来得到一个指向VB函数入口地址的指针,不过这个指针只能传递给API使用,以使得API能回调VB函数。

 

(4)CopyMemory函数

 

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDest As Any, pSource As Any, ByVal byteLen As Long)  

  功能是将从pSource指针所指处开始的长度为byteLen的内存拷贝到pDest所指的内存处。

  其中源地址和目标地址都是声明为Any类型。
下面是CopyMemory对不同形式参数的理解:
(1) 传一个变量给pSource,那么源地址就是变量所在的地址
(2) 以ByVal形式传一个变量给pSource,那么源地址就是变量的值


 例如:
 Dim k As Long
 k = 5
   '从保存常数40000的临时变量处拷贝4个字节,到变量k所在的内存中。
    
CopyMemory     ByVal VarPtr(k), 40000, 4      '[ByVal VarPtr(k)把K的地址本身当作值传给函数] 
 CopyMemory                          k  , 40000, 4     'K传递函数的缺省方法是ByRef, 因此, 也可这样写

    CopyMemory ByVal VarPtr(k), ByVal 40000, 4  
       ‘意思是从地址40000拷贝4个字节到变量k所在的内存中。由于地址40000所在的内存未知或不能访问,结果错误
    CopyMemory VarPtr(k), 40000, 4

       意思就成了,从保存常数40000的临时变量处拷贝4个字节,由于缺省是ByRef,VarPtr(k)为K的地址,将会成为一临时变量,再得到此临时变量的地址,传递给函数。此临时变量的内存地址无任何意义,k的值并没有变。

 

(5)字符串变量CopyMemory

 

     字符串变量的值是个指针,指向字符串缓冲区的地址,也就是StrPtr(Str1)。
     以ByVal形式传一个字符串变量给pSource,那么源地址就是字符串变量的值,也就是字符串缓冲区的地址。
 
下表总结了几种常见的传参数给CopyMemory的形式:
表格-CopyMemory使用字符串参数的各种可能形式
注:
(1)取到的内容根据byteLen实际规定的字节数的多少,可能有所不同,这里只是个大概。
(2)带高亮的两行,VB对字符串参数做了自动的UA转换,所以实际的CopyMemory动作针对的是由String1转换得到的ANSI字符串_tmp1而进行的。
(3)字节数那一列给出了要取到有效的数据byteLen参数可以使用的数字范围。简单的说,如果pSource的参数是字符串类型的话,那么byteLen的字节数要取为String1对应的ANSI字符串的长度。要理解这个也容易,你只要记住CopyMemory这时候实际上是对ANSI字符串做操作就可以了。而如果不发生字符串转换的话,像表里第4行,那么你就要拷贝String1的LebB长度。这也好理解,不发生转换的话,CopyMemory实际上是在直接拷贝Unicode字符串的内容啊。
 
Sub SwapPtr(sA As String, sB As String) Dim lTmp As Long  CopyMemory lTmp, ByVal VarPtr(sA), 4  CopyMemory ByVal VarPtr(sA), ByVal VarPtr(sB), 4  CopyMemory ByVal VarPtr(sB), lTmp, 4 End Sub Sub SwapStrPtr2(sA As String, sB As String) Dim lTmp As Long  Dim pTmp As Long, psA As Long, psB As Long  pTmp = VarPtr(lTmp):             psA = VarPtr(sA):                psB = VarPtr(sB) CopyMemory pTmp, psA, 4  CopyMemory psA, psB, 4  CopyMemory psB, pTmp, 4 End Sub 

'交换两个字符串最快的方法
Sub SwapStrPtr3(sA As String, sB As String) Dim lTmp As Long  Dim pTmp As Long, psA As Long, psB As Long  pTmp = StrPtr(sA):              psA = VarPtr(sA):                   psB = VarPtr(sB) CopyMemory ByVal psA, ByVal psB, 4  CopyMemory ByVal psB, pTmp, 4 End Sub 
参考:VB中利用CopyMemory使用指针
VB6中用CopyMemory拷贝字符串的种种猫腻(一)
0 0
原创粉丝点击