MoveMemoryの使い方

解決


プログラムはじめ  2010-08-08 06:29:35  No: 102495

いつもお世話になってます。
下記のページを参考にして変数のコピーをRtlMoveMemoryを使って行う方法を勉強中ですが、変なエラーがでてうまく行きません。

http://msdn.microsoft.com/en-us/library/aa366788(VS.85).aspx

Private Declare Sub MoveMemory Lib "kernel32" Alias "RtlMoveMemory" (ByVal Destination As Long, ByVal Source As Long, ByVal Length As Long)
Private Sub test()
    Dim a As String, b As String
    
    a = "あああaaa"
    Debug.Print LenB(a)
    MoveMemory VarPtr(b), VarPtr(a), LenB(a)
    MsgBox b

End Sub

LenB(a)をLen(a)に変えたらうまくいくようなのですが、第3引数にはコピーするバイト数を指定するのではないのでしょうか?ご教示ください。


花ちゃん  2010-08-08 21:51:38  No: 102496

>LenB(a)をLen(a)に変えたらうまくいくようなのですが、

a = "あああaaa"  では、Len(a)= 6 になり、異常終了しませんか?

>第3引数にはコピーするバイト数を指定するのではないのでしょうか?

多分、この場合は、文字列のポインタをコピーしているので、Long 型の
4 バイト固定でいいのではないでしょうか?

Private Sub test()
    Dim a As String, b As String
    a = "あああaaa"
    MoveMemory VarPtr(b), VarPtr(a), 4
    MsgBox b
    a = "a"
    MoveMemory VarPtr(b), VarPtr(a), 4
    MsgBox b
    a = "あああaaaあああaaa"
    MoveMemory VarPtr(b), VarPtr(a), 4
    MsgBox b
End Sub


プログラムはじめ  2010-08-09 02:00:11  No: 102497

花ちゃん様、ありがとうございます。
うまくいきました。
僕の最初の書き方のようにしようとすると一度byte型で受ける必要があると考えましたがあってますでしょうか?

Private Declare Sub MoveMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)

Private Sub test3()
    Dim a As String, b As String
    Dim c() As Byte, d() As Byte

    a = "あああaaa"
    ReDim c(0 To LenB(a) - 1)
    ReDim d(0 To LenB(a) - 1)
    c() = a
    MoveMemory d(0), c(0), UBound(c) + 1
    
    MsgBox d
    
End Sub


Abyss  2010-08-09 06:54:38  No: 102498

最初と、その後のAPI宣言で変数の渡す方法が違うのは
意図的なものですか?


プログラムはじめ  2010-08-09 07:27:58  No: 102499

Abyss様、いつもご指導ありがとうございます。
配列を引き渡すので参照引渡ししないとだめなのかと思いました。間違っていますでしょうかl?


Abyss  2010-08-09 07:39:54  No: 102500

いいえ。間違いとかではありません。
参照渡し、値渡しの問題がなければ良いとします。
気になっただけですので。


プログラムはじめ  2010-08-09 07:57:42  No: 102501

Abyss様、いつもありがとうございます。
APIは勉強を始めて日が浅く、まだまだ見習い状態です。今後ともなにかありましたらご指摘くださると非常にうれしいです。


Abyss  2010-08-09 08:19:38  No: 102502

今回のご質問はAPIよりVB6における
文字列(String型)の扱いが問題な気がします。

dim c() as byte
c = "あああaaa"

の場合、cは文字列(String型)ではありませんよね?
msgbox c

とした場合、VBが文字列への変換をしてくれただけです。


プログラムはじめ  2010-08-09 10:02:18  No: 102503

Abyss様
いつもお世話になっております。

>cは文字列(String型)ではありませんよね?
>msgbox c

>とした場合、VBが文字列への変換をしてくれただけです。

ここは意図してやっていました。花ちゃん様とAbyss様のご指導により、僕が当初理解できていなかったのは、文字列型の変数が参照型ということがわかっていなかったのだと気づきました。
string型変数を書き換えるときは参照型変数の確保領域の4バイトを引き渡して、Byte型を引き渡すときは、Byte数を引き渡す必要があると理解しましたが、あってますでしょうか?


Abyss  2010-08-09 10:34:05  No: 102504

> ここは意図してやっていました。
了解です。
> ...あってますでしょうか?
と思います。文字列をバイト単位で扱う一つの例です。

Declare Sub MoveMemory Lib "Kernel32" Alias "RtlMoveMemory" _
  (pDest As Any, pSrc As Any, ByVal cbLen As Long)
  
Sub Test()

  Dim a As String, c() As Byte
  
  a = "あああaaaあああaaaa"
  ReDim c(1 To LenB(a))
  MoveMemory c(1), ByVal StrPtr(a), LenB(a)
  MsgBox c
End Sub


Abyss  2010-08-09 10:56:37  No: 102505

学習のためですと↓のもご参考になるかと。
余計でしたらすみません。

  Dim a As String, c() As Byte
  Dim i As Long
  
  a = "あああaaaあああaaaa"
  'LenB(a)の代わり...
  MoveMemory i, ByVal StrPtr(a) - 4, 4
  MsgBox "文字列のバイト長=" & i
  
  ReDim c(1 To i)
  MoveMemory c(1), ByVal StrPtr(a), i
  MsgBox c


プログラムはじめ  2010-08-09 12:03:27  No: 102506

Abyss様ありがとうございます。

>MoveMemory c(1), ByVal StrPtr(a), LenB(a)

なるほど。勉強になります。今回の質問をさせていただくまで、StrPtr、VarPtrの違いがよく分かってなかったことにも気づきました。

>MoveMemory i, ByVal StrPtr(a) - 4, 4

bstr型についても、このように調べると書物で読むより、理解が深まります。本当にありがとうございました。とてもすっきりしました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加