14

memmove()の使用について2つの疑問があります:

  • 別の関数(つまり、作成された独自の関数)を使用する代わりに、この関数を使用することが望ましいのはいつですか?正しく理解できているかわかりません。
  • 関数のシグネチャはvoid*memmove(void * dest、const void * src、size_t n)です。単純な配列arr[N]がある場合、それを呼び出された関数に入れるにはどうすればよいですか?arr [N]または&arr [N]?違いは、配列が初期サイズで宣言されているか、ポインターのように宣言されているかです。両方が使用されている多くの例を見たので、私はこの疑問を持っています。

私は自分の疑問を良い方法で説明したことを願っています。

編集:配列から要素を削除する必要があります。次に、削除した要素の次の要素を左側にシフトします。

4

3 に答える 3

20
  1. memmove速いかもしれませんが、データをコピーするための独自の関数よりも遅くなることはないでしょう(通常、現在のアーキテクチャで可能な限り最も効率的な方法でデータを移動するために、慎重に作成されたアセンブリでコーディングされています)。
  2. その配列で何をしたいかによります...その内容を別の配列にコピーしたい場合arrは十分です(そして、長さパラメーターとして、sizeof(*arr)*NNはコピーする要素の数です)。

ちなみに、ソースと宛先とコピーが重複していないmemcpy場合は、より高速になる可能性があります。

配列から要素を削除し、同じ配列の要素を左にシフトしたいと思います。

int arr[N];
/* ... */
/* Let's say you want to remove the element i (error checking on i omitted) */
memmove(arr+i, arr+i+1, (N-i-1)*sizeof(*arr));
/* or, if you prefer array indexing over pointer arithmetics: */
memmove(&arr[i], &arr[i+1], (N-i-1)*sizeof(*arr));

sizeof(*arr)「配列の要素のサイズを取得する」という意味です)

于 2012-01-28T00:19:41.873 に答える
8

memmovememcpy宛先とソースの配列がオーバーラップする可能性があることを除いて、は似ています。

memcpyリージョンがオーバーラップしていないことを約束します。これにより、実装でいくつかの追加の最適化を実行できます。したがってmemcpy、より速くなる可能性がありますmemmove

このmemmove関数は、void *宛先引数とconst void *ソース引数を取ります。これは、配列型の宛先引数とソース引数を使用して関数を呼び出すことができることを意味します。これらはポインター型に変換されるためです。void *また、修飾されていないオブジェクトポインタタイプをまたはに割り当てることができるためconst void *、関数を呼び出すときにキャストは必要ありません。

char src[1024] = {0};
char dst[1024];

memmove(dst, src, sizeof dst);
/* src and dst don't overlap you should choose memcpy instead */
memcpy(dst, src, sizeof dst);

現在は、通常、独自の関数をコーディングするよりも、memcpyまたはを使用する方が適切です。memmoveたとえば、glibcでは、MCU命令セットとコピーするサイズに応じてmemcpy、コンパイラによって、の高速インラインアセンブリバージョンに置き換えることができますmemcpy

于 2012-01-28T00:20:13.363 に答える
0

別の関数(つまり、作成された独自の関数)を使用する代わりに、この関数を使用することが望ましい場合

「独自の関数を作成する」よりも高速です。

関数のシグネチャはvoid*memmove(void * dest、const void * src、size_t n)です。単純な配列arr[N]がある場合、それを呼び出された関数に入れるにはどうすればよいですか?arr [N]または&arr [N]

ただarr

于 2012-01-28T00:19:45.340 に答える