1. ホーム
  2. c

[解決済み] memcpy()とmemmove()の比較

2022-04-20 16:26:15

質問

との違いを理解しようとしています。 memcpy() memmove() という文章を読みました。 memcpy() は送信元と送信先の重なりを考慮しないのに対して memmove() があります。

しかし、この2つの関数を重複するメモリーブロックに対して実行すると、どちらも同じ結果になってしまうのです。たとえば、次のMSDNの例で memmove() ヘルプページ:-)

の欠点を理解するのに良い例はないでしょうか? memcpy と、どのように memmove は、それを解決するのですか?

// crt_memcpy.c
// Illustrate overlapping copy: memmove always handles it correctly; memcpy may handle
// it correctly.

#include <memory.h>
#include <string.h>
#include <stdio.h>

char str1[7] = "aabbcc";

int main( void )
{
    printf( "The string: %s\n", str1 );
    memcpy( str1 + 2, str1, 4 );
    printf( "New string: %s\n", str1 );

    strcpy_s( str1, sizeof(str1), "aabbcc" );   // reset string

    printf( "The string: %s\n", str1 );
    memmove( str1 + 2, str1, 4 );
    printf( "New string: %s\n", str1 );
}

出力します。

The string: aabbcc
New string: aaaabb
The string: aabbcc
New string: aaaabb

解決方法は?

あなたの例が奇妙な挙動を示さないことに、私はまったく驚いていません。試しに str1str1+2 の代わりに、"C "をつけて、何が起こるか見てみましょう。(実際には違いが出ないかもしれません。コンパイラやライブラリに依存します。)

一般に、memcpyはシンプルな(しかし高速な)方法で実装されています。単純に言えば、データを(順番に)ループして、ある場所から別の場所にコピーするだけです。このため、読み込み中にソースが上書きされることがあります。

Memmoveは、オーバーラップを正しく処理するために、より多くの作業を行います。

EDIT

(残念ながら、まともな例が見つからないが、これでいいだろう)。対照的に memcpy メモムーブ memcpyは単にループするだけですが、memmoveはデータの破損を避けるためにループする方向を決定するテストを行います。これらの実装はかなり単純なものです。ほとんどの高性能な実装はもっと複雑です(バイトではなくワードサイズのブロックを一度にコピーすることが含まれます)。