anonymous No title
No License VBA
2021年08月15日
Copy Clone
Option Explicit

Public Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
    (Destination As Any, _
     Source As Any, _
     ByVal Length As LongPtr)
Sub test()
    
    Dim strA As String
    Dim strB As String
    Dim btA(3) As Byte
    Dim btB(3) As Byte
    Dim i As Long
    
    strA = "AAAAAAAAAAAAAAAA"
    
    'VarPtr(strA)とはstrAの文字列の実体が置かれているアドレスが書かれているアドレス。
    '以下を実施することでstrBの文字列の実体が置かれているアドレスが書かれているアドレスに
    'strAの実体が置かれているアドレスが書き込まれる。
    Call CopyMemory(ByVal VarPtr(strB), ByVal VarPtr(strA), 4)
    
    'Midステートメントの実施
    Mid(strA, 3, 2) = "BB"
        
    'strAに変更を加えたのにstrBにも影響が
    Debug.Print "両者の文字列を表示"
    Debug.Print strA
    Debug.Print strB
    
    '文字列の実体が書かれているアドレスを取得
    Call CopyMemory(btA(0), ByVal VarPtr(strA), 4)
    Call CopyMemory(btB(0), ByVal VarPtr(strB), 4)
    
    '同じ文字列の実体を指し示している2つの変数なのでstrBにも影響が出るのは当然
    'Midステートメントは文字列の実体を操作しているだけと想像できる
    Debug.Print vbCr & "両者の文字列の実体のアドレス"
    For i = 0 To 3
        Debug.Print Hex(btA(i)) & " ";
    Next i
    Debug.Print ""
    For i = 0 To 3
        Debug.Print Hex(btB(i)) & " ";
    Next i
    Debug.Print ""
    
    'Midステートメントのやっていることを想像
    '3文字目は先頭アドレス+4バイト目(1文字目0バイト1バイト、2文字目2バイト3バイト)
    'どこかに用意した"BB"のアドレスから2文字(4バイト分)
    'Call CopyMemory(ByVal StrPtr(strA) + 4, ByVal StrPtr("BB"), 4)
    '↑Midステートメントの代わりにMidステートメントと同じ場所で実施すれば同じ結果となる
    
    'Replace
    strA = Replace(strA, "BB", "CC")
    
    '今度はstrBには影響しない
    Debug.Print vbCr & "両者の文字列を表示"
    Debug.Print strA
    Debug.Print strB
    
    '文字列の実体が書かれているアドレスを取得
    Call CopyMemory(btA(0), ByVal VarPtr(strA), 4)
    Call CopyMemory(btB(0), ByVal VarPtr(strB), 4)
    
    '違う文字列の実体を指し示している。
    'Replaceのコードを見れば、strAに代入してしまったので別の文字列の実体を指し示すようになったということ。
    Debug.Print vbCr & "両者の文字列の実体のアドレス"
    For i = 0 To 3
        Debug.Print Hex(btA(i)) & " ";
    Next i
    Debug.Print ""
    For i = 0 To 3
        Debug.Print Hex(btB(i)) & " ";
    Next i
    Debug.Print ""
    
    '文字数を取得(文字列の実体より前4バイトで文字数を表す)
    Dim btC(3) As Byte
    Call CopyMemory(btC(0), ByVal StrPtr(strA) - 4, 4)
    
    'リトルエンディアンで20=32バイト=16文字と分かる
    Debug.Print vbCr & "strAの文字数を取得"
    For i = 0 To 3
        Debug.Print Hex(btC(i)) & " ";
    Next i
    Debug.Print ""
    
    'こんなことしちゃって良いの?
    '文字数変更で8文字(16バイト)
    btC(0) = 16
    Call CopyMemory(ByVal StrPtr(strA) - 4, btC(0), 4)
    
    Debug.Print vbCr & "8文字に変更したstrAの表示"
    Debug.Print strA
    
    '終端が00じゃ無いんですけど!!(16バイト目が00になっていない)
    Dim btD(31) As Byte
    Call CopyMemory(btD(0), ByVal StrPtr(strA), 32)
    Debug.Print vbCr & "strAの8文字とstrAより後の8文字を表示"
    Debug.Print btD
    Debug.Print "↑strAの終端が00じゃ無いんですけど!!"
    
End Sub
Option Explicit

Public Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
    (Destination As Any, _
     Source As Any, _
     ByVal Length As LongPtr)
Sub test()
    
    Dim strA As String
    Dim strB As String
    Dim btA(3) As Byte
    Dim btB(3) As Byte
    Dim i As Long
    
    strA = "AAAAAAAAAAAAAAAA"
    
    'VarPtr(strA)とはstrAの文字列の実体が置かれているアドレスが書かれているアドレス。
    '以下を実施することでstrBの文字列の実体が置かれているアドレスが書かれているアドレスに
    'strAの実体が置かれているアドレスが書き込まれる。
    Call CopyMemory(ByVal VarPtr(strB), ByVal VarPtr(strA), 4)
    
    'Midステートメントの実施
    Mid(strA, 3, 2) = "BB"
        
    'strAに変更を加えたのにstrBにも影響が
    Debug.Print "両者の文字列を表示"
    Debug.Print strA
    Debug.Print strB
    
    '文字列の実体が書かれているアドレスを取得
    Call CopyMemory(btA(0), ByVal VarPtr(strA), 4)
    Call CopyMemory(btB(0), ByVal VarPtr(strB), 4)
    
    '同じ文字列の実体を指し示している2つの変数なのでstrBにも影響が出るのは当然
    'Midステートメントは文字列の実体を操作しているだけと想像できる
    Debug.Print vbCr & "両者の文字列の実体のアドレス"
    For i = 0 To 3
        Debug.Print Hex(btA(i)) & " ";
    Next i
    Debug.Print ""
    For i = 0 To 3
        Debug.Print Hex(btB(i)) & " ";
    Next i
    Debug.Print ""
    
    'Midステートメントのやっていることを想像
    '3文字目は先頭アドレス+4バイト目(1文字目0バイト1バイト、2文字目2バイト3バイト)
    'どこかに用意した"BB"のアドレスから2文字(4バイト分)
    'Call CopyMemory(ByVal StrPtr(strA) + 4, ByVal StrPtr("BB"), 4)
    '↑Midステートメントの代わりにMidステートメントと同じ場所で実施すれば同じ結果となる
    
    'Replace
    strA = Replace(strA, "BB", "CC")
    
    '今度はstrBには影響しない
    Debug.Print vbCr & "両者の文字列を表示"
    Debug.Print strA
    Debug.Print strB
    
    '文字列の実体が書かれているアドレスを取得
    Call CopyMemory(btA(0), ByVal VarPtr(strA), 4)
    Call CopyMemory(btB(0), ByVal VarPtr(strB), 4)
    
    '違う文字列の実体を指し示している。
    'Replaceのコードを見れば、strAに代入してしまったので別の文字列の実体を指し示すようになったということ。
    Debug.Print vbCr & "両者の文字列の実体のアドレス"
    For i = 0 To 3
        Debug.Print Hex(btA(i)) & " ";
    Next i
    Debug.Print ""
    For i = 0 To 3
        Debug.Print Hex(btB(i)) & " ";
    Next i
    Debug.Print ""
    
    '文字数を取得(文字列の実体より前4バイトで文字数を表す)
    Dim btC(3) As Byte
    Call CopyMemory(btC(0), ByVal StrPtr(strA) - 4, 4)
    
    'リトルエンディアンで20=32バイト=16文字と分かる
    Debug.Print vbCr & "strAの文字数を取得"
    For i = 0 To 3
        Debug.Print Hex(btC(i)) & " ";
    Next i
    Debug.Print ""
    
    'こんなことしちゃって良いの?
    '文字数変更で8文字(16バイト)
    btC(0) = 16
    Call CopyMemory(ByVal StrPtr(strA) - 4, btC(0), 4)
    
    Debug.Print vbCr & "8文字に変更したstrAの表示"
    Debug.Print strA
    
    '終端が00じゃ無いんですけど!!(16バイト目が00になっていない)
    Dim btD(31) As Byte
    Call CopyMemory(btD(0), ByVal StrPtr(strA), 32)
    Debug.Print vbCr & "strAの8文字とstrAより後の8文字を表示"
    Debug.Print btD
    Debug.Print "↑strAの終端が00じゃ無いんですけど!!"
    
End Sub
No one still commented. Please first comment.