VBA数据类型Variant

2020-07-28 10:14:48 浏览数 (1)

官方文档定义:A special data type that can contain numeric, string, or date data as well as user-defined types and the special values Empty and Null. The Variant data type has a numeric storage size of 16 bytes and can contain data up to the range of a Decimal, or a character storage size of 22 bytes (plus string length), and can store any character text. The VarType function defines how the data in a Variant is treated. All variables become Variant data types if not explicitly declared as some other data type.

我以前一直好奇为什么能有什么数据都可以保存的类型,现在对内存知识有了一定了解才知道,其实说到底,Variant底层也是一种数据结构,16个字节分别会有不同的意义,对于一些VBA里的对象复制给Variant后,也只是保存了它的地址。至于通过地址怎么就能判断出对象的具体类型就不大清楚了!

所以想知道Variant的16个字节具体代表了什么,我们只需要让它保存不同的数据类型,然后查看16个字节的变化就可以了。

Variant16字节是如何分配的?

  1. 前8字节 b0:标识数据类型(也就是VarType返回的数字) b1:标识后8字节是数据还是指针 - 0x00 8-15数据类型的是数据本身,String是地址 - 0x40 8-11存的是数据地址,String是地址的地址 - 0x20 8-11存的是数组地址 - 0x60 8-11存的是数组地址的地址
  2. 后8字节8-15:数据或地址
代码语言:javascript复制
Sub TestVariant()
    Dim v As Variant
    Dim i As Byte

    i = &H10
    v = i

    Dim lenth As Long
    lenth = 16

    Dim b() As Byte
    ReDim b(lenth - 1) As Byte

    CopyMemory VarPtr(b(0)), VarPtr(v), lenth
    Printf "VarType(v) = 0x%x, b = 0x% x", VarType(v), b
End Sub

输出:
i定义byte:VarType(v) = 0x11, b = 0x11 00 00 00 00 00 00 00 10 00 00 00 00 00 00 00
i定义Integer:VarType(v) = 0x2, b = 0x02 00 00 00 00 00 00 00 10 00 00 00 00 00 00 00
i定义Long:VarType(v) = 0x3, b = 0x03 00 00 00 00 00 00 00 10 00 00 00 00 00 00 00
i定义Double:VarType(v) = 0x5, b = 0x05 00 00 00 00 00 00 00 00 00 00 00 00 00 30 40
i定义String:VarType(v) = 0x8, b = 0x08 00 00 00 00 00 00 00 74 02 f3 23 00 00 00 00

b1一直都是0,就算用v = VarPtr(i),仍然是0,因为VarPtr返回的也是Long,如何才能让b1出现呢?我们知道,VBA里面,函数的传值默认就是byref,所以加1个Function就可以了。

代码语言:javascript复制
Sub TestVariant()
        Dim i As Byte

        i = &H10
        TestVariantPtr i
    End Sub

    Function TestVariantPtr(v As Variant)
        Dim lenth As Long
        lenth = 16

        Dim b() As Byte
        ReDim b(lenth - 1) As Byte

        CopyMemory VarPtr(b(0)), VarPtr(v), lenth

        Dim ptr As Long
        CopyMemory VarPtr(ptr), VarPtr(b(8)), 4

        Dim Value As Byte
        CopyMemory VarPtr(Value), ptr, 2

        Printf "VarType(v) = 0x%x, b = 0x% x, ptr = 0x%x, Value = %x", VarType(v), b, ptr, Value
    End Function
    输出:
    i、Value定义byte:VarType(v) = 0x11, b = 0x11 40 00 00 00 00 00 00 52 ef 19 00 00 00 00 00, ptr = 0x19efe4, Value = 10
    i、Value定义Integer:VarType(v) = 0x2, b = 0x02 40 00 00 00 00 00 00 52 ef 19 00 00 00 00 00, ptr = 0x19efe4, Value = 10
    i、Value定义Long:VarType(v) = 0x3, b = 0x03 40 00 00 00 00 00 00 50 ef 19 00 00 00 00 00, ptr = 0x19ef50, Value = 10

其他不多演示,注意Dim Value As语句下面的CopyMemory复制字节数和Value类型保持一致。

0 人点赞