C编程。如何深度复制结构?

时间:2009-09-24 23:01:29

标签: c struct memcpy deep-copy

我有以下两个结构,其中“child struct”有一个“rusage struct”作为元素。

然后我创建两个类型为“child”的结构,让我们称它们为childA和childB

如何将childA的rusage结构复制到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));

我知道这给了childB来自childA的所有值。我已经处理了childB中的其他字段,我只需要能够复制驻留在“子”结构中的名为usage的rusage结构。

7 个答案:

答案 0 :(得分:20)

简单地:

childB.usage = childA.usage;

答案 1 :(得分:10)

不应该是:

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

答案 2 :(得分:2)

编辑:好的,我误解了这个问题,你只想复制用法字段;所以我的回答有点无关。我不删除它,因为在分配或复制包含指针的结构时,它仍然可以提醒初学者潜在的别名问题。

当然,memcpy或其他答案的分配将起作用。结构中唯一的危险来自指向名称的指针。如果将一个结构复制到另一个结构,则两个结构都包含相同指针并指向相同的内存。您创建了一个别名。这意味着如果yoy更改分配空间中的名称,它将从其他结构中可见。此外,如果您将结构传递给标准自由函数,则存在双free的危险。 要真正复制结构,你应该做类似的事情:

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

或者

childA = childB;
if(childB.name)
  childA.name = strdup(childB.name);

答案 3 :(得分:0)

首先,正确的代码是

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

第二,这将复制值asis,因此对于所有那些长和时间结构它将是安全的, 但是您拥有的char * name参数将指向相同的原始值。

答案 4 :(得分:0)

childB.usage = childA.usage

由于您在子结构中拥有整个结构,因此简单的复制就足够了。如果你有一个指向子结构内部的rusage结构的指针,那可能是个问题。在这种情况下,您将不得不为childB.usage分配内存,然后执行memcpy,以便如果有人修改/删除childA,则childB将不会受到伤害。

答案 5 :(得分:0)

正如其他人所提到的那样,你可以通过两种方式获得两种方式。

1)childB.usage = childA.usage;
2)memcpy(& childB.usage,& childA.usage,sizeof(rusage));

memcpy的第一个参数是目标,第二个是源,第三个是length(要复制的字节数)。从你发布的代码中,你试图将整个childB复制到childA,这真的不是你想要的。

答案 6 :(得分:0)

在这个文件中我将原始成员复制到destinazione,首先只使用赋值和strcpy,然后,我只使用memcpy将原始复制到memres

#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;
}