最近まで、構造化フィールドのコピーがmemcpy()
で行われるのを見てきました。クラスとオンラインの手順では、1つの構造体の内容を別の構造体にコピーすると、通常は次のようになります。
_struct block *b0 = malloc(sizeof(struct block));
struct block *b1 = malloc(sizeof(struct block));
/* populate fields in *b0 */
memcpy(b1, b0, sizeof *b1); /* copy contents of b0 into b1 */
/* free b0, b1 */
_
ただし、このタスクは、memcpy()
を置き換える簡単な割り当てでも実行できます。
_*b1 = *b0; /* dereferenced struct assignment */
_
これが(少なくとも私の限られた経験では)広く使用されていない理由はありますか?これらの2つのメソッド(代入とmemcpy()
)は同等ですか、または一般にmemcpy()
を使用する説得力のある理由はありますか?
どちらの方法も同等であり、浅いコピーを実行します。つまり、構造自体はコピーされますが、構造が参照するものはコピーされません。
なぜmemcpy
の方が人気があるのかはわかりません。古いバージョンのCは構造体の割り当てをサポートしていません( 1978年には一般的な拡張機能でしたが )。したがって、より移植性のあるコードを作成する方法としてmemcpyスタイルがスタックしているのではないでしょうか?いずれにせよ、PCコンパイラでは構造体の割り当てが広くサポートされており、memcpy
を使用するとエラーが発生しやすくなります(サイズが間違っていると、悪いことが発生する可能性があります)。したがって、構造体の割り当てを使用することをお勧めします可能であれば。
ただし、memcpy
のみが機能する場合があります。例えば:
memcpy
を使用する必要があります。構造体の割り当てにはソースと適切に位置合わせされる宛先。memcpy
を使用して、この追加情報をサイズフィールドに含める必要があります。memcpy
を実行する方がmayより効率的です個別に。それでも、そうではないかもしれません。 memcpy
実装のパフォーマンス特性は異なります。Cではmemcpy
と構造体の割り当ては通常同等ですが、C++ではmemcpy
と構造体の割り当てはnotであることにも注意してください同等。一般的にC++では、構造体の割り当てがオーバーロードされてディープコピーや参照カウント管理などの追加の処理を実行できるため、memcpy
ing構造体を回避するのが最善です。
これはあなたが探している正確な答えにはなりません。
私が出会ったシナリオを説明しています。
memcpy()
を使用すると、宛先にバイト単位でコピーされます。したがって、ARMアーキテクチャではデータのアライメントについて心配する必要はありません。=
演算子、およびアドレスのいずれかが4バイトにアラインされていない場合、アラインメントエラーが発生します。
From Arm site:
書き込まれた最後のバイトを1バイト超えた宛先位置へのポインター。これにより、書き込みプロセスを継続できますwith perfect alignment of bytes
メモリブロックの文字列連結。
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0175k/Cihbbjge.html
答えが説明しないので、この古い質問を復活させますなぜmemcpy
が実際に優先されます。
memcpy
は、プログラマーが単にポインターではなくコンテンツをコピーしたいことを明確にするため、推奨されます。
次の例では、2つの割り当ては2つの非常に異なることを行います。
struct Type *s1,*s2;
*s1=*s2;
s1=s2;
誤って一方を他方の代わりに使用すると、悲惨な影響が生じる可能性があります。コンパイラーは文句を言いません。初期化されていないポインタが使用されたときにプログラムがクラッシュしない限り、エラーは長時間気付かれないままになり、奇妙な副作用を引き起こす可能性があります。
次のいずれかとして記述します。
memcpy(s1,s2,sizeof(*s1));
memcpy(s1,s2,sizeof(*s2));
memcpy(s1,s2,sizeof(struct Type));
意図はコンテンツをコピーすることであることを読者に知らせてください(タイプセーフと境界チェックを犠牲にして)。
一部のコンパイラ(gccなど)は、次のような状況に遭遇すると、sizeofに関する警告を発行します。
memcpy(s1,s2,sizeof(s1));
一部の人々はmemcpyを好みます。なぜなら、それが彼らが学んだことであり、彼らが割り当てだけを行うことができることを理解しなかったからです(古代には割り当ては許可されませんでしたが、それはずっと前のことです)。 malloc()によって割り当てられたメモリは常に正しく整列されるため、心配する必要のある整列の問題はありません。また、コンパイラはこの割り当てをmemcpy呼び出しに簡単に変換できるため、memcpyよりもコードが遅くなったり、コードが増えたりすることはありません。もちろん、時代遅れのコンパイラが組み込まれた組み込みシステムもあります。