こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

構造体のデータを丸ごとコピーしたい

C言語の構造体の勉強をしています。
構造体のデータを丸ごとコピーしたいのですが、今までは下記プログラムの★1の方法で1つ1つやっていました。

しかし変数が増えてきたのでできれば一度にコピーをしたいのですが、★2の方法では場合によってはゴミが含まれてしまいます。

そこで★3の方法で試すと今のところコピーできたのですが、これは安全なのでしょうか?

ご存知の方がおられればお願いします。
また、もっといい方法があればご伝授いただけると助かります。



#include <stdio.h>
#include <string.h>

struct Sample{
 int val1;
 int val2;
};

void test(Sample *p, int num){
 Sample d;

 switch(num){
 case 1: //★1
  d.val1 = p->val1;
  d.val2 = p->val2;
 break;
 case 2: //★2
  memcpy(&d, p, sizeof(Sample));
  break;
 case 3: //★3
  d = *p;
  break;
 }

 printf("val1:%d, val2:%d\n", d.val1, d.val2);
}

int main(){
 Sample s;
 s.val1 = 1;
 s.val2 = 2;

 test(&s, 1);
 return 0;
}

投稿日時 - 2008-07-24 17:29:45

QNo.4201042

暇なときに回答ください

質問者が選んだベストアンサー

Cであれば、★2でも★3でも問題ありません。
★2の方法では、パディング部分の不定値もそのままコピーしますが、そもそもパディング部分にアクセスしたり、ましてやその値に依存したコードを書くこと自体間違っていますので、何の問題もありません。

ところで...

>  Sample s;

という宣言を見る限り、(structが省略されているので)C++ではないかと思います。
C++の場合、memcpyで構造体をコピーできるのはC互換型(POD型)に限られます。その他のクラス(構造体を含む)をmemcpyでコピーすることはできません。
そのため、常に★3の方法を採用する方が無難です。

なお、構造体のメンバにポインタや参照を含む場合には、その参照先までコピー(すなわちディープコピー)を行うには、適切な代入演算子を定義する必要があります。
C++ではなくCの場合、専用のコピー関数を作るなどして対応する必要があります。

投稿日時 - 2008-07-25 01:47:59

ANo.6

このQ&Aは役に立ちましたか?

111人が「このQ&Aが役に立った」と投票しています

回答(6)

ANo.5

★2でもコピーできると思ったんですけどゴミってなんでしょう
★2は関数呼ぶ分だけ手間がかかりますが結果は★3と同じだと思うんですが

投稿日時 - 2008-07-24 19:05:16

ANo.4

sizeof は「実際にメモリ上で構造体が占めるバイト数」を返します>#2.
つまり, アラインメントの都合上パディングが入る場合には, そのパディングも含めたバイト数になります. じゃないと配列を動的に確保できない.

投稿日時 - 2008-07-24 18:24:21

ANo.3

ISO の規格に従っている処理系なら ★3 でコピーできることが保証されています.

投稿日時 - 2008-07-24 18:05:23

ANo.2

★3でとくに問題はないです。

>★2の方法では場合によってはゴミが含まれてしまいます。
どの部分にゴミが入るかが記載されていませんが、構造体をmem系のAPIで扱うことはあまりよろしくありません。sizeof()を使用する場合も注意が必要です。
細かい理由は省きますが、「構造体で定義されているメンバの合計Byte数」=「実際にメモリ上に展開されている構造体のByte数」にはならないためです。
詳しいことは「構造体」「アライメント」「パディング」で調べてみてください。

投稿日時 - 2008-07-24 18:04:49

ANo.1

★3が一般的な方法だと思います
問題はないはずです

投稿日時 - 2008-07-24 17:50:32