2009-09-24 13 views
8

私は「子構造体は、」要素として「のrusage構造体」を持って次の二つの構造体を持っています。Cプログラミング。構造体をディープコピーする方法は?

その後、私はタイプの2つの構造体を作成し、「子供が」私はchildAからchildBにちょうどのrusage構造体をコピーするにはどうすればよいchildAとchildB

のは、彼らを呼びましょうか?

typedef struct{       
     int numb; 
     char *name; 
     pid_t pid; 
     long userT; 
     long systemT; 
     struct rusage usage; 
}child; 


typedef struct{ 
    struct timeval ru_utime; /* user time used */ 
    struct timeval ru_stime; /* system time used */ 
    long ru_maxrss;  /* maximum resident set size */ 
    long ru_ixrss;   /* integral shared memory size */ 
    long ru_idrss;   /* integral unshared data size */ 
    long ru_isrss;   /* integral unshared stack size */ 
    long ru_minflt;  /* page reclaims */ 
    long ru_majflt;  /* page faults */ 
    long ru_nswap;   /* swaps */ 
    long ru_inblock;  /* block input operations */ 
    long ru_oublock;  /* block output operations */ 
    long ru_msgsnd;  /* messages sent */ 
    long ru_msgrcv;  /* messages received */ 
    long ru_nsignals;  /* signals received */ 
    long ru_nvcsw;   /* voluntary context switches */ 
    long ru_nivcsw;  /* involuntary context switches */ 

}rusage; 

私は次のことをやったが、私はchildAでの使用の値を変更した場合、それはまたchildBに変化するので、私は、メモリの場所にコピーを推測します。

memcpy(&childA,&childB, sizeof(rusage)); 

私が知っているのはchildAのすべての値をchildBに与えていることです。私はすでにchildBの他のフィールドの世話をしました。私はちょうど "子"構造体にあるuseというrusage構造体をコピーできる必要があります。

+0

すべてのご提案の仕事が、私が今までchildAを変更する場合:あなたはそのような何かを行う必要があり、構造体の真の複製を作るために childBも変更されます。 – user69514

+0

コードに問題があります。あなたの質問に対するすべての返答は正しいものであり、あなたが望む効果を生み出します。それがうまくいかない場合、問題は他の場所にあります。 –

+0

@uknown - つまり、2つの構造インスタンスが同じアドレスにある(つまり、同じインスタンスである)か、2つの異なるアドレスでデータの2つの異なるインスタンスが変更されている(つまり、間違っているあなたが報告しているもので)。 – ChrisW

答えて

20

単に:

childB.usage = childA.usage; 
+0

memcpy()よりも速く、確かに遅くはありません。 –

+0

@Jonathan、コンパイラはおそらくmemcpyを使用します – leiz

+0

memcpy()を明示的に使用するのではなく、それをサポートするCの最も古いバージョンが何かを覚えていますか? –

10

が、それはすべきではない:

memcpy(&(childB.usage), &(childA.usage), sizeof(rusage)) 
+0

memcpyの最初のパラメータは宛先です。したがって、AをBにコピーするには、Aを2番目に指定する必要がありますparam。 –

+0

もちろん、構造体にポインタがある場合は、値を重複させるためには何らかの作業をする必要がありますが、コピーする構造体にはポインタがないので、memcpyは大丈夫です。 –

+0

+1 - 私はあなたのロジックに同意します。これは、rusageにはポインタがないため、これは正常に動作するはずです。 –

0

まず、正しいコードが

memcpy(&childA,&childB, sizeof(child)); 

秒で、これは値ASISをコピーします、のためので、すべてのそれらの長いと時間の構造体は、それは安全です しかし、あなたが持っているchar * nameパラメータは、ポインタ同じ元の値に戻します。

+0

これは、 "childAからchildBへのrusage構造体のコピー"ではなく、全体の子をコピーします。 – ChrisW

+0

あなたの権利、私は質問の終わりを誤読 – Amirshk

0

childB.usage = childA.usage

あなたは子構造体の内部構造全体を持っているので、単純なコピーで十分。子構造内にrusage構造体へのポインタがあれば、問題になっている可能性があります。その場合、あなたはchildB.usageのためのメモリを割り当てた後、誰が変更する場合/ childA、childBは無事だろう削除されますようにのmemcpyをしなければならなかっただろう。

0

あなたは可能性が他の人が言及したように2つの方法で、2。

1)childB.usage = childA.usage。
2)のmemcpy(& childB.usage、& childA.usage、はsizeof(のrusage))。

memcpyの最初の引数はデスティネーション、2番目はソース、3番目は長さ(コピーするバイト数)です。投稿したコードからchildB全体をchildAにコピーしようとしていましたが、これは本当にあなたが望んでいないものです。 [OK]を、私は質問を読み違える:私はdestinazioneに原産地のメンバーをコピーし、このファイルに

0

、唯一の割り当てとstrcpyのを使用して最初の、そして、私は唯一のmemcpy

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

typedef struct inner 
{ 
    char *parola; 
    int n; 
} interna; 

typedef struct outer 
{ 
    struct inner *ptr; 
    int numeroesterno; 
} esterna; 


struct another 
{ 
    struct inner *ptr; 
    int numero; 
}; //never forget ; here 

int main(void) 
{ 
    esterna *origine; //ptr to structs 
    struct another *destinazione; 
    struct another *memres; 

    char *tmpParola; 
    tmpParola = malloc(30*sizeof(char)); 
    strcpy(tmpParola, "AAAAA"); 

    interna *tmp; //remember the TYPEDEF, and don't use struct interna 
    tmp = (interna *)malloc(sizeof(struct inner)); 
    // if you use struct interna in sizeof you get 
    // error: invalid application of ‘sizeof’ to incomplete type ‘struct interna’ 

    tmp->n = 500; 
    tmp->parola = tmpParola; 

    origine = (esterna *)malloc(sizeof(struct outer)); 

    origine->numeroesterno = 2; 
    origine->ptr = tmp; //the data structer pointed by tmp has already been allocated and set 

    // now I have the structure allocated and set, I want to copy this on destinazione 
    destinazione = (struct another *)malloc(sizeof(struct another)); 

    destinazione->numero = origine->numeroesterno; 

    //destinazione->ptr = tmp; //in this case you don't copy struct inner, it's just a reference 

    destinazione->ptr = (interna *)malloc(sizeof(struct inner)); 
    destinazione->ptr->parola = malloc(sizeof(char)*30); 
    strcpy(destinazione->ptr->parola, origine->ptr->parola); 
    destinazione->ptr->n = 111; 

    //modify origine 

    origine->numeroesterno = 9999; 
    strcpy(origine->ptr->parola, "parola modificata in origine"); 

    //print destinazione 

    printf("\nparola in destinazione :%s\n", destinazione->ptr->parola); 
    printf("\nparola in origine :%s\n", origine->ptr->parola); 

    //you can see that destinazione is a copy, because mofifying origine, destinazione deosn't change 

    //now we play with memcpy 

    memres = (struct another *)malloc(sizeof(struct another)); 

    memcpy(memres, destinazione, sizeof(destinazione)); //till here, is AAAAA 
    strcpy(destinazione->ptr->parola, "parola modificata in destinazione"); 

    printf("\nmemcpy, numero %d\n", memres->numero); 
    printf("\nmemcpy, parola :%s\n", memres->ptr->parola); 

    //as you can see from the output, memcpy doesn't make a copy of destinazione: 
    //modifying destinazione->ptr->parola after the assignment affects what memres carries with it 
    //So from the idea that I got, memcpy just creates the pointers to the originary structure 

    free(origine->ptr->parola); 
    free(origine->ptr); 
    return 0; 
} 
2

EDITを使用して、memresに原産地をコピーします使用分野をコピーするだけでした。私の答えは少し無関係です。ポインタを含む構造体を割り当てたり複製したりするときに、潜在的なエイリアシング問題の初心者に思い出させることができるので、私はそれを削除しません。

memcpyまたは他の回答の割り当ては、もちろん動作します。あなたの構造における唯一の危険は、名前へのポインタから来ています。ある構造体を他の構造体にコピーすると、同じポインタと同じメモリを指す両方の構造体があります。エイリアスを作成しました。つまり、割り当てられた領域の名前を変更すると、他の構造体から表示されます。さらに、構造体を標準のフリー関数に渡すと、doubleの危険があります。free 、childAの正確なコピーを作成する

memcpy(&childA,&childB, sizeof(rusage));  
if(childB.name) 
    childA.name = strdup(childB.name); 

または代わり

childA = childB; 
if(childB.name) 
    childA.name = strdup(childB.name); 
関連する問題