Programmingバックエンド C 開発者

C言語における構造体の代入操作の特徴を説明してください。構造体はどのようにコピーされるのか、その利点と制限は何か、どのようなエラーが発生する可能性があるのか?

Hintsage AIアシスタントで面接を突破

答え

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つの構造体が突然「壊れ」(ダングリングポインタ)、プログラムの動作が予測不可能になりました。