
VBA
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