r...........t

解决方案 »

  1.   

    '---------------------------------------------------------------------------------------
    ' 过程名    : TestVariant
    ' 时间      : 2013/3/30
    ' 作者      : 杨过.网狐.cn(csdn bcrun)
    ' 功能      :
    ' 说明      :
    ' 备注      : 星辰设计室VB一群:283362041,星辰学园BASIC辅导群:289219875
    '---------------------------------------------------------------------------------------
    Public Sub TestVariant()
        Dim arrVar As Variant
        Debug.Print TypeName(arrVar)
        arrVar = Array("a1", "b2", "c3")
        Debug.Print TypeName(arrVar)
        Debug.Print TypeName(arrVar(LBound(arrVar)))
        Debug.Print VarPtr(arrVar(LBound(arrVar)))  '数组的首元素的地址
        
    End Sub
      

  2.   

    谢谢。很奇怪,内置byte()是就不行了。    Dim arrVar As Variant
        Dim a() As Byte
        ReDim a(2)
        a(0) = 0
        a(1) = 10
        a(2) = 20
        Debug.Print TypeName(arrVar)
        arrVar = a
        Debug.Print TypeName(arrVar)
        Debug.Print TypeName(arrVar(LBound(arrVar)))
        Debug.Print VarPtr(arrVar(LBound(arrVar)))  '数组的首元素的地址
        Debug.Print VarPtr(arrVar(LBound(arrVar) + 1))
      

  3.   

    不是Byte的问题,从你这个测试来看,对Variant变量arrVar直接赋值数组后,VarPtr(arrVar())这样的操作并非取得实际的元素地址,那就不用钻牛角尖了。需要直接访问地址时,先再赋值回给一个标准的动态数组再处理吧:arrVar = a
    Dim b() As Byte
    b = arrVar 
      

  4.   

    这个东西我查过MSDN,没找到说明。
    你说的这种情况,我估计很可能编译环境是把arrVar()处理成类似函数返回值的形式了,所以不管括号你的数字是几,对应的varptr都一样。想想VB里的mid()即可放在=左边又可放在右边,唉,怎么处理最终还是编译器说了算。其实啊,各种语言里都能多少找到一些疑似BUG的语法或编译器处理的方式,如果看重代码的易读和易移植性的话,应尽量避免使用这类写法,或者实在需要这样写时,认真写好代码注释。BTW,前几天在这个帖子的8楼回复了一段有点关系的代码,这里提一下
    ByVal 与 ByRef求解
      

  5.   

    这不能跟C语言相比,VB的数组是安全数组,实际地址是有偏移的。
    参考下面:http://blog.csdn.net/laviewpbt/article/details/4216686
      

  6.   

    那要自己解析Variant的结构.....有点多,太麻烦了哈哈.typedef struct FARSTRUCT tagVARIANT VARIANT;
    typedef struct FARSTRUCT tagVARIANT VARIANTARG;typedef struct tagVARIANT  {
        VARTYPE vt;
        unsigned short wReserved1;
        unsigned short wReserved2;
        unsigned short wReserved3;
        union {
            unsigned char        bVal;                        // VT_UI1.
            short                    iVal;                        // VT_I2    .
            long                    lVal;                        // VT_I4    .
            float                    fltVal;                    // VT_R4    .
            double                dblVal;                    // VT_R8    .
            VARIANT_BOOL        boolVal;                        // VT_BOOL.
            SCODE                    scode;                    // VT_ERROR.
            CY                        cyVal;                    // VT_CY    .
            DATE                    date;                        // VT_DATE.
            BSTR                    bstrVal;                    // VT_BSTR.
            IUnknown                FAR* punkVal;            // VT_UNKNOWN.
            IDispatch             FAR* pdispVal;            // VT_DISPATCH.
            SAFEARRAY            FAR* parray;            // VT_ARRAY|*.
            unsigned char        FAR* pbVal;                // VT_BYREF|VT_UI1.
            short                    FAR* piVal;                // VT_BYREF|VT_I2.
            long                    FAR* plVal;                // VT_BYREF|VT_I4.
            float                    FAR* pfltVal;            // VT_BYREF|VT_R4.
            double                FAR* pdblVal;            // VT_BYREF|VT_R8.
            VARIANT_BOOL        FAR* pboolVal;                // VT_BYREF|VT_BOOL.
            SCODE                    FAR* pscode;            // VT_BYREF|VT_ERROR.
            CY                        FAR* pcyVal;            // VT_BYREF|VT_CY.
            DATE                    FAR* pdate;                // VT_BYREF|VT_DATE.
            BSTR                    FAR* pbstrVal;            // VT_BYREF|VT_BSTR.
            IUnknown FAR*        FAR* ppunkVal;            // VT_BYREF|VT_UNKNOWN.
            IDispatch FAR*        FAR* ppdispVal;        // VT_BYREF|VT_DISPATCH.
            SAFEARRAY FAR*        FAR* pparray;            // VT_ARRAY|*.
            VARIANT                FAR* pvarVal;            // VT_BYREF|VT_VARIANT.
            void                    FAR* byref;                // Generic ByRef.
        };
    };先得到地址,再去解析......
      

  7.   

    VB高级编程里面有些关于Variant的介绍,你可以参阅一下,应该有所启发。
    http://download.csdn.net/detail/veron_04/1371398
      

  8.   

    Option ExplicitType userVARIANT
        vt              As Integer
        wReserved1      As Integer
        wReserved2      As Integer
        wReserved3      As Integer
        dwReserved1     As Long
        dwReserved2     As Long
    End TypeConst VT_BYREF = &H4000Sub Main()
        Dim arrVar      As Variant
        Dim a()         As Byte
        ReDim a(2)
        Debug.Print Hex(VarPtr(a(0)))    arrVar = a
        Debug.Print Hex(GetpvData(VarPtr(arrVar)))    TestByRef a
        TestByVal a
    End SubFunction GetpvData(ByVal pV As Long) As Long
        Dim v           As userVARIANT
        Dim sa          As SafeArray
        Dim pSA         As Long    CopyMemory v, ByVal pV, Len(v)
        If CBool(v.vt And VT_BYREF) Then
            CopyMemory pSA, ByVal v.dwReserved1, 4
        Else
            pSA = v.dwReserved1
        End If    CopyMemory sa, ByVal pSA, Len(sa)
        GetpvData = sa.pvData
    End FunctionSub TestByRef(ByRef arrVar As Variant)
        Debug.Print Hex(GetpvData(VarPtr(arrVar)))
    End SubSub TestByVal(ByVal arrVar As Variant)
        Debug.Print Hex(GetpvData(VarPtr(arrVar)))
    End Sub
    没加容错处理。
      

  9.   

    可以看出 TestByRef 是对原数组的引用,直接赋值和 TestByVal 都复制了数组。
      

  10.   

    赵老虎的函数:Function GetpvData(ByVal pV As Long) As Long
        Dim v           As userVARIANT
        Dim sa          As SafeArray
        Dim pSA         As Long
     
        CopyMemory v, ByVal pV, Len(v)
        If CBool(v.vt And VT_BYREF) Then
            CopyMemory pSA, ByVal v.dwReserved1, 4
        Else
            pSA = v.dwReserved1
        End If
     
        CopyMemory sa, ByVal pSA, Len(sa)
        GetpvData = sa.pvData
    End Function
    嗯,这就是解析VARIANT及SAFEARRAY的具体实现了。
      

  11.   


    http://www.cnblogs.com/pctgl/articles/1540556.html
    获取安全数组信息
     
    Des:
    获取安全数组的信息,包括安全数组结构内的所有数据
    本来用结构做的话,更方便,但会增加代码量,而且用起来也会麻烦些,所以就用了N多变量了
    有兴趣的朋友可以再改改Private Function GetSafeArrayInfo(AnyArray As Variant, Optional sDimension As Integer, Optional LowerBound As Long, Optional UpperBound As Long, Optional Elements As Long, Optional Flags As Integer, Optional cbElements As Long, Optional cLocks As Long, Optional AddressOfData As Long) As Long
    '**************************************************************
    '*
    '*  数组头地址 = GetSafeArrayInfo(数组 ,[维数],[下标],[上标],[元素个数],[属性],[元素长度],[锁定计数],[首元素地址])
    '*
    '*  result:  成功返回数组头地址;  返回 0 代表这是一个未被初始化过的数组
    '*
    '*  note:    除第1个参数外,均为输出型参数,要获取数组的什么信息,传入相应的变量,执行后,变量的值即为相应的数组数据
    '*
    '*           要获取多维数组的非第1维的上/下标,应按照下面的方法调用
    '*
    '*           GetSafeArrayInfo (数组, 指定一个维数,[下标],[上标]
    '*
    '**************************************************************    Dim ArrayHeaderAddress  As Long
        Dim DimensionCount As Integer     '维数计次    CopyMemory ArrayHeaderAddress, ByVal VarPtr(AnyArray) + 8, 4
        CopyMemory ArrayHeaderAddress, ByVal ArrayHeaderAddress, 4              '获取数组头地址
       
        If ArrayHeaderAddress < 1 Then Exit Function    CopyMemory DimensionCount, ByVal ArrayHeaderAddress, 2                  '获取数组维数    If sDimension > DimensionCount Then Exit Function                       '若指定的维数大于实际维数则退出    CopyMemory LowerBound, ByVal (ArrayHeaderAddress + 16 + (DimensionCount - sDimension) * 8) + 4, 4 '获取下标
        CopyMemory Elements , ByVal (ArrayHeaderAddress + 16 + (DimensionCount - sDimension) * 8), 4                                                   '获取指定维数下的元素个数
        UpperBound = Elements + LowerBound - 1                                '获取指定维数下的上标
       
        CopyMemory Flags, ByVal ArrayHeaderAddress + 2, 2                       '获取数组属性
        CopyMemory cbElements, ByVal ArrayHeaderAddress + 4, 2                  '获取数组单个元素长度
        CopyMemory cLocks, ByVal ArrayHeaderAddress + 8, 2                      '获取数组锁定计数
        CopyMemory AddressOfData, ByVal ArrayHeaderAddress + 12, 4              '获取数组首元素地址
       
        GetSafeArrayInfo = ArrayHeaderAddress
     
    End Function
      

  12.   

    要如LS那么复杂?VarPtr(A(0)),不行吗?