了解RtlMoveMemory

时间:2019-02-19 11:24:42

标签: vba

感谢您阅读本文。我出于好奇而试图理解这一点。我从某个地方复制了此代码,尝试弄乱,但无法按预期工作。我希望Debug.Print c返回4,但仍保持3。我怀疑该错误可能是数据类型,但不确定,因为没有错误弹出窗口。

Option Explicit

#If VBA7 Then
    Declare PtrSafe Sub CopyMemory Lib "kernel32.dll" Alias _
            "RtlMoveMemory" (ByRef Destination As LongPtr, ByRef Source As LongPtr, _
            ByVal Length As LongPtr)
#Else
    Declare PtrSafe Sub CopyMemory Lib "kernel32.dll" Alias _
           "RtlMoveMemory" (Destination As Long, Source As Long, _
            ByVal Length As Long)
#End If

Sub Main2()
    Dim c As Long, d As Long

    c = 3
    Move2 VarPtr(c)
    Debug.Print c

End Sub

Sub Move2(ByVal pointerOfi As LongPtr)
    Dim tempvalue As Long

    CopyMemory VarPtr(tempvalue), pointerOfi, LenB(pointerOfi)
    tempvalue = tempvalue + 1
    CopyMemory pointerOfi, VarPtr(tempvalue), LenB(pointerOfi)

End Sub

1 个答案:

答案 0 :(得分:2)

您对CopyMemory的参数的声明不包含ByVal关键字,因此所有参数均通过引用传递(ByRef),这意味着:

CopyMemory VarPtr(tempvalue), pointerOfi, LenB(pointerOfi)

CopyMemory传递了2个长值(它们是评估VarPtr(tempvalue)pointerOfi结果的引用(地址),而不是这些变量包含的实际值。

如果您有一个包含内存地址的变量,那么您需要传递值本身,而不是包含值的变量地址:

CopyMemory ByVal VarPtr(tempvalue), ByVal pointerOfi, LenB(pointerOfi)

请注意,您可以利用ByRef的优势,完全不用担心原始指针的存在:

Sub Main2()
    Dim c As Long, d As Long

    c = 3
    Move2 c
    Debug.Print c
End Sub

Sub Move2(x As Long)
    Dim tempvalue As Long

    CopyMemory tempvalue, x, LenB(tempvalue)
    tempvalue = tempvalue + 1
    CopyMemory x, tempvalue, LenB(x)
End Sub