You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

VBA实现指针时MoveMemory返回异常值,结果不符预期求助

问题根源分析

你的代码核心问题出在AL_Address函数的参数传递逻辑上:

  • 当把Integer类型变量a传递给ByVal Variant类型的参数Variable时,VBA会自动将a装箱为一个临时Variant对象。
  • VarPtr(Variable)获取的是这个临时Variant对象的内存地址,而非原变量a的真实地址。
  • 解引用临时Variant的地址时,读取的是Variant结构的类型标识(VT)部分,而非原变量的实际值,因此得到错误的16387。
修正方案

1. 为特定类型编写地址函数

由于VBA不支持函数重载,我们可以为每种需要支持的数据类型编写单独的地址函数,通过ByRef参数确保获取原变量的真实地址:

Private Declare PtrSafe Sub MoveMemory Lib "kernel32.dll" Alias "RtlMoveMemory" _
    (ByVal Destination As LongPtr, ByVal Source As LongPtr, ByVal Length As Long)

' Integer类型的地址获取函数
Public Function AL_Address_Integer(ByRef var As Integer) As LongPtr
    AL_Address_Integer = VarPtr(var)
End Function

' Integer类型的解引用函数
Private Function AL_DeRef_Integer(Pointer As LongPtr) As Integer
    MoveMemory VarPtr(AL_DeRef_Integer), Pointer, Len(AL_DeRef_Integer)
End Function

Sub Test()
    Dim a As Integer, b As Integer, c As Integer
    a = 1: b = 2: c = 0
    ' 直接调用对应类型的地址和解引用函数
    c = AL_DeRef_Integer(AL_Address_Integer(a))
    Debug.Print a
    Debug.Print b
    Debug.Print c
End Sub

2. 通用地址函数优化(可选)

如果需要支持多种数据类型,可以通过ByRef Variant参数结合Variant内部结构获取原变量地址,需区分32/64位系统的结构差异:

Public Function AL_Address(ByRef var As Variant) As LongPtr
    Dim vt As Integer
    ' 读取Variant的类型标识
    MoveMemory VarPtr(vt), VarPtr(var), Len(vt)
    Select Case vt
        Case vbInteger, vbByte, vbBoolean
            ' 值类型直接存储在Variant的偏移位置(32位偏移4字节,64位偏移8字节)
            #If Win64 Then
                AL_Address = VarPtr(var) + 8
            #Else
                AL_Address = VarPtr(var) + 4
            #End If
        ' 其他数据类型可按需扩展
    End Select
End Function
验证结果

运行修正后的Test过程,输出将符合预期:

1
2
1

内容的提问来源于stack exchange,提问作者Almesi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 12:14:51