web-dev-qa-db-ja.com

ある構造を別の構造にコピーする

私はメンバーごとに構造体をコピーできることを知っていますが、代わりに構造体にmemcpyを実行できますか?

そうすることをお勧めしますか?

私の構造体には、同じメンバーを持つ別の構造体にコピーする必要があるストリングもメンバーとしてあります。それ、どうやったら出来るの?

51
asir

短く、読みやすく、抽象度が高いため、単純な割り当てによるコピーが最適です。 「コードの人間の読者に」「これらのビットをここからそこにコピーする」と言って、読者にコピーのサイズ引数について考えるように要求する代わりに、単純な割り当てを行います(「この値をここからここへ」)。サイズが正しいかどうかをためらうことはありません。

また、構造が非常にパディングされている場合、パディングをコピーする必要がないため(そして、それがどこにあるかを知っているため)、コンパイラーはより効率的に何かを出力する可能性がありますが、mempcy()はそうしませんコピーするように指示した正確なバイト数が常にコピーされます。

文字列が実際の配列の場合、つまり:

struct {
  char string[32];
  size_t len;
} a, b;

strcpy(a.string, "hello");
a.len = strlen(a.string);

その後、プレーン割り当てを引き続き使用できます。

b = a;

完全なコピーを取得します。ただし、このようにモデル化された可変長データの場合、配列全体が常にコピーされるため、これはコピーを実行する最も効率的な方法ではありません。

ただし、ヒープに割り当てられたメモリへのポインタを含む構造体のコピーは、危険です。これを行うと、aliasingポインタになり、通常、コピー後にポインタを所有する人が曖昧になるためです。操作。

これらの状況では、「ディープコピー」が実際に唯一の選択肢であり、それを機能に組み込む必要があります。

62
unwind

C90以降、単純に次を使用できます。

dest_struct = source_struct;

文字列が配列内に記憶されている限り:

struct xxx {
    char theString[100];
};

それ以外の場合、ポインターの場合は、手動でコピーする必要があります。

struct xxx {
    char* theString;
};

dest_struct = source_struct;
dest_struct.theString = malloc(strlen(source_struct.theString) + 1);
strcpy(dest_struct.theString, source_struct.theString);
38
Simone

構造が互換性のあるタイプである場合、はい、次のようなものでできます:

memcpy (dest_struct, source_struct, sizeof (*dest_struct));

注意する必要があるのは、これがshallowコピーであることだけです。つまり、特定の文字列を指すchar *がある場合、both構造体は同じ文字列を指します。

また、これらの文字列フィールドの1つのコンテンツ(char *自体ではなく、char *が指すデータ)を変更すると、もう一方も変更されます。

手動で各フィールドを実行する必要がなく、非浅い文字列コピーの追加ボーナスを使用して簡単なコピーが必要な場合は、strdupを使用します。

memcpy (dest_struct, source_struct, sizeof (*dest_struct));
dest_struct->strptr = strdup (source_struct->strptr);

これにより、構造体のコンテンツ全体がコピーされ、文字列がディープコピーされ、各構造体に個別の文字列が効果的に与えられます。

また、C実装にstrdup(ISO標準の一部ではない)がない場合は、 ここから取得 になります。

16
paxdiablo

memcpy構造体を使用することも、他の値と同様に割り当てることもできます。

struct {int a, b;} c, d;
c.a = c.b = 10;
d = c;
5
Conrad Meyer

Cでは、memcpyは愚かに危険なだけです。 3つのパラメーターすべてを正確に取得している限り、構造体のメンバーはいずれもポインターではなく(または、浅いコピーを明示的に行うことを意図しています)、memcpyがループ処理に時間を浪費する大きな構造上のギャップはありません(またはパフォーマンスは重要ではありません)、それから必ずmemcpyです。読みづらく、将来の変更に対して脆弱で、コードレビューで手作業で検証する必要があるコード(コンパイラーができないため)以外は何も得られませんが、そうでないのは確かです。

C++では、ばかげたリスクに進みます。 std :: stringのように、安全にmemcpyableではない型のメンバーが存在する場合があります。これにより、受信する構造体が危険な武器になり、使用時にメモリがランダムに破損します。スライスコピーをエミュレートする際に、仮想関数に関する驚きを感じるかもしれません。 =をコンパイルするときに完全な型知識を保証しているため、驚くべきことを行うことができるオプティマイザーは、memcpy呼び出しに対して何も実行できません。

C++には経験則があります-memcpyまたはmemsetが表示された場合、何かが間違っています。これが当てはまらないまれなケースがありますが、構造体は含まれません。 memcpyは、blindly copy bytesの理由がある場合にのみ使用します。

一方、割り当ては読みやすく、コンパイル時に正確性をチェックし、実行時にvaluesをインテリジェントに移動します。欠点はありません。

1
user15001

次のソリューションを使用して、目標を達成できます。

struct student 
{
    char name[20];
    char country[20];
};
void main()
{
    struct student S={"Wolverine","America"};
    struct student X;
    X=S;
    printf("%s%s",X.name,X.country);
}
0
Anvesh