2009-09-24 24 views
8

Tengo las siguientes dos estructuras donde "estructura infantil" tiene una "estructura rusage" como elemento.C Programación. ¿Cómo copiar profundamente una estructura?

Luego de crear dos estructuras de tipo "niño" llamémosles Childa y Parto de

Cómo puedo copiar sólo la estructura de rusage Childa al Parto de ¿Cómo?

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; 

hice lo siguiente, pero supongo que copia la ubicación de la memoria, porque si he cambiado el valor de uso en Childa, también cambia en el Parto de.

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

Sé que da a childB todos los valores de childA. Ya me he ocupado de los otros campos en childB, solo necesito poder copiar la estructura de rusage llamada usage que reside en la estructura "child".

+0

todo su trabajo sugerencia para hacer una copia exacta de Childa, pero si alguna vez cambiar Childa, childB también cambia. – user69514

+0

Hay algo más incorrecto con su código. Todas las respuestas a su pregunta son correctas y producirán el efecto que desee. Si no funciona, el problema está en otra parte. –

+0

@uknown - eso significa que las dos instancias de la estructura están en la misma dirección (es decir, que son la misma instancia), o que algo está cambiando dos instancias distintas de los datos en dos direcciones diferentes (o que estás equivocado en lo que estás informando). – ChrisW

Respuesta

20

Simplemente:

childB.usage = childA.usage; 
+0

Mucho más simple, posiblemente más rápido que memcpy() y ciertamente no más lento. –

+0

@Jonathan, el compilador probablemente usa memcpy – leiz

+0

¿Alguien puede recordar cuál es la versión más antigua de C que lo admite, en lugar de tener que usar memcpy() explícitamente? –

10

¿No debería ser:

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

El primer parámetro en memcpy es el destino, por lo tanto, para copiar de A a B, necesita el lugar A como segundo param. –

+0

Y, por supuesto, si tiene un puntero en la estructura, necesitaría hacer más trabajo para hacer un valor duplicado, pero en su ejemplo, la estructura que desea copiar no tiene punteros, por lo que memcpy debería estar bien . –

+0

+1 - Estoy de acuerdo con su lógica de que, dado que el rusage no tiene punteros, esto debería funcionar bien. –

0

en primer lugar, el código correcto es

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

segundo, esto copiará los valores de ASIS, por lo que para todas esas estructuras largas y temporales estarán seguras, , pero el parámetro char * name que tiene apunta al mismo valor original.

+0

Eso copiará al hijo completo, no "copiará solo la estructura de rusage de childA a childB". – ChrisW

+0

tienes razón, leí mal el final de la pregunta – Amirshk

0

childB.usage = childA.usage

Puesto que usted tiene toda la estructura interior de la estructura niño, copia simple es suficiente. Si tuvieras un puntero a la estructura de rusage dentro de la estructura hija, podría haber sido un problema. En ese caso, habría tenido que asignar memoria para childB.usage y luego hacer una memcpy para que si alguien modifica/elimina childA, childB quedará intacto.

0

Puede dos de dos maneras, como otros han mencionado.

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

El primer argumento de memcpy es el destino, el segundo es la fuente y el tercero es la longitud (la cantidad de bytes que desea copiar). Del código que has publicado, intentabas copiar todo el hijoB a childA, que realmente no es lo que querías.

0

en este archivo copio los miembros de origine a destinazione, primeros sólo se utilizan asignaciones y strcpy, a continuación, copio origine a memres, utilizando sólo 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: Ok, leí mal la pregunta , solo quería copiar el campo de uso; entonces mi respuesta no está relacionada. No lo elimino porque todavía puede recordarles a los principiantes el posible problema de alias cuando asigna o duplica una estructura que contiene punteros.

El memcpy o la asignación de las otras respuestas funcionarán, por supuesto. El único peligro en sus estructuras proviene del puntero para nombrar.Si copia una estructura a la otra, tendrá ambas estructuras que contienen el mismo puntero y apuntando a la misma memoria. Usted creó un alias. esto significa que si cambia el nombre en el espacio asignado, será visible desde la otra estructura. Además, existe el peligro de un doble free si pasa su estructura a la función estándar libre. hacer un verdadero duplicado de la estructura que debe hacer algo así:

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

o alternativamente

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