8
votes

C Programmation. Comment faire une copie en profondeur une structure?

J'ai les deux structures suivantes où "enfant struct" a une "structure de rusage" comme élément.

Puis je crée deux structs de type "enfant" appelons-les de l'enfant et de la chambre p>

Comment copier juste la structure de rusion de l'enfant à maillette? P> xxx pré>

J'ai procédé à ce qui suit, mais je suppose qu'il copie l'emplacement de la mémoire, car si j'ai changé la valeur de l'utilisation Dans Enfile, il change également dans la petite enfance. P>

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


4 commentaires

Toutes vos suggestions fonctionnent pour effectuer une copie exacte de l'enfant, mais si je change jamais à l'enfant, la petite pièce change également.


Il y a quelque chose d'autre mal avec votre code. Toutes les réponses à votre question sont correctes et produiront l'effet que vous désirez. Si cela ne fonctionne pas, le problème est ailleurs.


@Unknown - Cela signifie que les deux instances de structure sont à la même adresse (c'est-à-dire qu'elles sont la même instance), ou que quelque chose change deux instances distinctes des données à deux adresses différentes (ou que vous êtes trompé dans ce que vous rapportez).


Êtes-vous Assurez-vous que vous n'avez pas struct rusage * Utilisation dans la définition de struct enfant , plutôt que ce que vous avez montré?


7 Réponses :


21
votes

Simplement:

childB.usage = childA.usage;


5 commentaires

Beaucoup le plus simple - éventuellement plus rapide que memcpy () et certainement pas plus lent.


@Jonathan, le compilateur utilise probablement memcpy


Quelqu'un peut-il se souvenir de quelle est la version la plus ancienne de C qui soutient que, plutôt que d'utiliser memcpy () explicitement?


@LEIZ, j'aurais deviné que la bibliothèque de temps d'exécution est plus susceptible de dépendre du compilateur que de vice versa, c'est-à-dire que (au lieu de ce que vous avez dit) MEMCY pourrait être implémentée en utilisant le même compilateur intrinsèque que le compilateur utilise pour attribuer un structure.


@Leiz: Le compilateur utilise probablement REP MOVSB, la structure de copie à la structure est intégrée à C, et s'il utilise MEMCY sous-hotte, il s'agit probablement de la conception (c'est-à-dire que le compilateur C plus portable). @CRAIG: C Supporte-le dès le début, vous n'avez pas besoin de #include la mémoire de la bibliothèque.h pour pouvoir effectuer une copie de la mémoire de type de valeur. De même, l'attribution de la structure à un pointeur de structure indirecte fonctionne également.



10
votes

ne devrait-il pas être: xxx


3 commentaires

Le premier paramètre de MEMCY est la destination, de sorte de copier A à B, vous avez besoin de placer un deuxième param.


Et bien sûr, si vous avez un pointeur dans la structure, vous devrez faire une autre solution pour effectuer une valeur en double, mais dans votre exemple, la structure que vous souhaitez copier n'a pas de pointeurs, alors Memcpy devrait donc être correct.


+1 - Je suis d'accord avec votre logique que puisque la rusion n'a pas de pointeurs, cela devrait fonctionner correctement.



0
votes

Premièrement, le code correct est

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


1 commentaires

Cela copiera tout l'enfant, pas "Copier uniquement la structure d'utilisation de l'enfant à l'enfant".



0
votes

Childb.Usage = Enfonda.Unage

Puisque vous avez la structure entière à l'intérieur de la structure de l'enfant, une copie simple suffit. Si vous aviez un pointeur à la structure de rusion dans la structure de l'enfant, cela aurait pu être un problème. Dans ce cas, vous auriez dû allouer la mémoire pour mailled.Usage et ensuite faire un memcpy de sorte que si quelqu'un modifie / supprime l'enfant, la petite taille sera indemne.


0 commentaires

0
votes

Vous pourriez deux que de deux manières, comme d'autres l'ont mentionné.

1) Childb.Usage = Enfonda.Usage;
2) memcpy (& couled.Unsage, & encadré.Unage, taille de (rusion));

Premier argument de MEMCY est la destination, la seconde est la source et que la troisième est la longueur (combien d'octets que vous souhaitez copier). Du code que vous avez affiché, vous essayiez de copier tout l'enfant à Enfile, ce qui n'est vraiment pas que vous vouliez.


0 commentaires

0
votes

Dans ce fichier, je copie les membres de l'origine à Destinazione, en utilisant d'abord des affectations et Strcpy, puis je copie l'origine des MEMRES, en utilisant uniquement 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;
}


0 commentaires

3
votes

EDIT: OK, j'ai mal interprété la question, vous ne vouliez que copier le champ d'utilisation; Donc, ma réponse est un peu non liée. Je ne le supprime pas car il peut encore rappeler les débutants du problème d'aliose potentiel lors de l'attribution ou du double de la structure contenant des pointeurs contenant de la structure.

memcpy ou attribution des autres réponses fonctionnera , bien sûr. Le seul danger de votre structure vient du pointeur à nommer. Si vous copiez une structure à l'autre, vous aurez les deux structures contenant le pointeur le même et la pointe de la même mémoire. Vous avez créé un alias. Cela signifie que si vous changez le nom dans l'espace alloué, il sera visible de l'autre structure. De plus, il y a le danger d'un double gratuit si vous passez votre structure à la fonction libre standard. Pour faire un vrai duplicata de la struct, vous devez faire quelque chose comme ça: xxx

ou alternativement xxx


0 commentaires