132

memmoveとはどう違いmemcpyますか?普段どちらをどのように使用していますか?

4

9 に答える 9

171

を使用memcpyすると、宛先はソースとまったくオーバーラップできません。それでmemmoveできます。これは、同じ仮定を行うことができないため、memmoveよりもわずかに遅い可能性があることを意味します。memcpy

たとえば、memcpyアドレスを常に低いものから高いものにコピーする場合があります。宛先が送信元の後で重複している場合、これは一部のアドレスがコピーされる前に上書きされることを意味します。memmoveこの場合、これを検出し、反対方向(高から低)にコピーします。ただし、これを確認して別の(おそらく効率の低い)アルゴリズムに切り替えるには時間がかかります。

于 2009-07-29T16:03:17.163 に答える
34

memmove重複するメモリを処理できますが、memcpyできません。

検討

char[] str = "foo-bar";
memcpy(&str[3],&str[4],4); //might blow up

明らかに、ソースと宛先が重複しているため、「-bar」を「bar」で上書きしています。ソースと宛先がオーバーラップするかどうかを使用するのは未定義の動作なmemcpyので、この場合はが必要memmoveです。

memmove(&str[3],&str[4],4); //fine
于 2009-07-29T16:03:53.153 に答える
23

memcpyのman ページから。

memcpy() 関数は、メモリ領域 src からメモリ領域 dest に n バイトをコピーします。メモリ領域はオーバーラップしてはなりません。メモリ領域がオーバーラップする場合は、memmove (3)を使用します。

于 2009-07-29T16:02:41.830 に答える
10

一方 ( memmove) は重複する宛先を処理し、もう一方 ( memcpy) は処理しません。

于 2009-07-29T16:02:37.150 に答える
7

ISO/IEC:9899 規格から簡単に説明されています。

7.21.2.1 memcpy 関数

[...]

2 memcpy 関数は、s2 が指すオブジェクトから s1 が指すオブジェクトに n 文字をコピーします。重複するオブジェクト間でコピーが行われる場合、動作は未定義です。

7.21.2.2 memmove 関数

[...]

2 memmove 関数は、s2 が指すオブジェクトから s1 が指すオブジェクトに n 文字をコピーします。コピーは、s2 が指すオブジェクトの n 文字が最初に、s1 および s2 が指すオブジェクトと重複しないn 文字の一時配列にコピーされ、次に一時配列の n 文字が次の場所にコピーされるかのように行われます。 s1 が指すオブジェクト。

質問に従って、私が通常使用するものは、必要な機能によって異なります。

プレーンテキストではオーバーラップは許可されmemcpy()ませんが、whileは許可されます。s1s2memmove()

于 2015-05-08T10:48:32.097 に答える
1

実装する明白な方法が 2 つありますmempcpy(void *dest, const void *src, size_t n)(戻り値を無視します)。

  1. for (char *p=src, *q=dest;  n-->0;  ++p, ++q)
        *q=*p;
    
  2. char *p=src, *q=dest;
    while (n-->0)
        q[n]=p[n];
    

最初の実装では、コピーは低アドレスから高アドレスに進み、2 番目の実装では、高アドレスから低アドレスに進みます。コピーする範囲が重なっている場合 (たとえば、フレームバッファをスクロールする場合など)、一方の方向の操作のみが正しく、もう一方の方向は後で読み取られる場所を上書きします。

最も単純な実装では、 (プラットフォームに依存する方法で)memmove()テストし、適切な方向を実行します。dest<srcmemcpy()

もちろん、ユーザーコードはそれを行うことはできません。キャストして具体的なポインター型に変換した後でも、src(dst一般に) 同じオブジェクトを指していないため、比較できないためです。しかし、標準ライブラリは、未定義の動作を引き起こすことなく、そのような比較を実行するのに十分なプラットフォームの知識を持つことができます。


実際には、大規模な転送 (アラインメントが許す場合) および/または適切なデータ キャッシュの使用率から最大のパフォーマンスを得るために、実装はかなり複雑になる傾向があることに注意してください。上記のコードは、要点をできるだけ単純にするためのものです。

于 2016-05-30T15:18:05.470 に答える
0

memmove は重複するソース リージョンと宛先リージョンを処理できますが、memcpy は処理できません。2 つのうち、memcpy ははるかに効率的です。したがって、可能であれば memcpy を使用することをお勧めします。

参照: https://www.youtube.com/watch?v=Yr1YnOVG-4g Jerry Cain 博士、(Stanford Intro Systems Lecture - 7) 時間: 36:00

于 2016-12-10T02:46:01.740 に答える