VarPtr 得到地址 指针

在Basic语言演变成QBasic,然后到Visual Basic之前,VarPtr函数就已经存在了。开始,这个函数存在于VB运行库1.0版中。通过声明可以调用这个函数:

Declare Function VarPtr Lib "vbrun100.dll" (Var As Any) As Long

数年之后,vbrun100.dll变成了msvbvm50.dll,但该函数的入口点却还在那儿。为了获取变量的地址,只须将变量名传递给该函数就行了。例如:

Dim l As Long
Debug.Print VarPtr(l)

类似地,为了获取字符串的指针,而非保存字符串的变量的指针,只须在变量名前加上ByVal即可。如:

Debug.Print VarPtr(s),VarPtr(ByVal s)

在VB3之前,用这种方法来获取字符串缓冲的指针是非常普遍的。但在VB4却遇到了一点麻烦。

ANSI/UNIDCODE问题

随着32位世界和VB4的到来,我们迈进了一半是UNICODE,一半是ANSI的Windows世界。而在此之前,是ANSI一统天下。在VB中,所有字符串按UNICODE保存,但所有的API调用却仍使用ANSI字符串。这就要求在调用API函数之前,将字符串从UNICODE转换成ANSI,函数执行结束后,将返回的字符串从ANSI转换成UNICODE。虽然大多数时候这种转换对用户来说是透明的,但这就使利我们不能将一个字符串类型的参数以UNICODE方式从VB传递给DLL。类似地,任何包含有字符串的结构在执行API调用时,也必须经过这种双重转换。

这种差异是如何影响VarPtr函数的呢?当一个字符串传递给VarPtr函数时,函数执行后所返回的地址是保存临时ANSI字符串的临时ANSI字符串或变量的地址。换句话说,这个地址并不是你声明的变量的真正地址。因此,对于字符串变量以及包括字符串的结构来讲,这个函数一点用也没有。

VB5来解决问题

为了能VarPtr能重新发挥作用,VB5(及Office97)加入了三个针对VBA类型库的入口点。这些入口点为VarPtr函数提供了内置的声明。这三个函数的作用是:

VarPtr:返回变量地址

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

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

VarPtr其函数原型如下,用OleView打开c:windowssystem32msvbvm60.dll可知:

[entry(0x60000006), hidden]

long _stdcall VarPtr([in] void* Ptr);

请看下两个例子:

例一:

Dim s As Long:s=-11                 ‘为非指针型变量均可,如Byte等,会转化成Long。

MsgBox VarPtr(s)                      ‘得到变量s的地址

MsgBox VarPtr(-11)                   ‘得到临时变量的地址

MsgBox VarPtr(ByVal s)            ‘不用建立临时变量,结果为-11。如果VarPtr为取址,肯定不会为-11;此处不取址了,仅转化值。

例二:

Dim s As string:s=”asdfg”

MsgBox VarPtr(s)                      ‘得到变量s的地址

MsgBox VarPtr(“asdfg”)            ‘得到临时变量的地址

MsgBox VarPtr(ByVal s)            ‘得到字符串”asdfg”的地址

上面两例的结果均为Long型,且前两个地址数值相近,因均属变量型,而最后一个为常量。

VB不鼓励使用指针,比如MsgBox s,单独用变量名s,就是无法得地址。VarPtr的最大作用,当然是突破限制、“抠”出了变量的指针数值。那“数值转化”有什么用呢?其实没什么特别。我们来自己定义个VarPtr,在例一中加上Private Declare Function VarPtr Lib "msvbvm60.dll" (x As Any) As Integer,会进行Long与Integer的转换。

再看例三,三个MsgBox的结果相同:

例三:

Dim s As Long:s = -11

MsgBox VarPtr(s)

MsgBox VarPtr(ByVal VarPtr(s))       ‘不可省去ByVal,那会是临时变量的地址

Dim t As Long

t = VarPtr(s)

MsgBox VarPtr(ByVal t)

End

可以看出,实参中ByVal VarPtr(x)的搭配和(ByRef) x一样;VarPtr(ByVal x)和x一样。

原文地址:https://www.cnblogs.com/rosesmall/p/3298241.html