zoukankan      html  css  js  c++  java
  • 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一样。

  • 相关阅读:
    LeetCode 137. Single Number II
    LeetCode 16. 3Sum Closest
    LeetCode 18. 4Sum
    LeetCode 15. 3Sum
    LeetCode 166. Fraction to Recurring Decimal
    LeetCode Anagrams
    Java: Difference between ArrayList and LinkedList
    LeetCode 242. Valid Anagram
    LeetCode 204. Count Primes
    Java Class Variable/Static Variable
  • 原文地址:https://www.cnblogs.com/rosesmall/p/3298241.html
Copyright © 2011-2022 走看看