Cは同じ型の構造体を直接代入することをサポートしています:すべてのフィールドがバイト単位でコピーされます(memcpy)。これは、構造体を迅速にクローンするために便利です。たとえば:
struct Point { int x, y; }; struct Point p1 = {10, 20}; struct Point p2; p2 = p1; // 現在、p2.x=10, p2.y=20
特徴:
「構造体が動的に確保されたメモリへのポインタを含んでいる場合、構造体を別の構造体に代入すると何が起こりますか?」
多くの人はすべての内容がコピーされると思っていますが、そうではありません。
答え: ポインタの値(アドレス)だけがコピーされ、アドレス内のデータはコピーされません。両方の構造体のオブジェクトは、同じメモリを指し示すことになります。
struct Data { int *arr; }; struct Data d1; d1.arr = malloc(10 * sizeof(int)); struct Data d2 = d1; // d2.arr == d1.arr
変更後、d2.arrを変更すると、d1.arrが見るメモリも変更されます。
物語 1
データのシリアル化:内部バッファのポインタ(malloc)を持つ構造体を代入した後、2つの異なるオブジェクトが同じメモリを指し示し、両方がfree()を呼び出した結果、ダブルフリーが発生し、サービスがクラッシュしました。
物語 2
複雑な構造体をクローンしようとして、ポインタのフィールドの深いコピーを作成するのを忘れました。コピーを変更した後、独立性を期待しましたが、オリジナルを変更することになり(逆も然り)、データの整合性を失いました。
物語 3
文字列へのネストされたポインタを持つ構造体を保持していました。構造体を代入した後、1つの文字列を解放したところ、もう1つの構造体が突然「壊れ」(ダングリングポインタ)、プログラムの動作が予測不可能になりました。