Copier une structure dans une autre

Je sais que je peux copier le membre de la structure par membre, au lieu de cela, puis-je faire un memcpy sur les structures?

Est-il conseillé de le faire?

Dans ma structure, j’ai aussi une chaîne en tant que membre que je dois copier dans une autre structure ayant le même membre. Comment je fais ça?

Copier par simple affectation est préférable, car il est plus court, plus facile à lire et possède un niveau d’abstraction plus élevé. Au lieu de dire (au lecteur humain du code) “copier ces bits d’ici à là” et demander au lecteur de réfléchir à l’argument de taille de la copie, vous ne faites qu’une simple affectation (“copiez cette valeur de ici pour ici “). Il ne peut y avoir aucune hésitation quant à savoir si la taille est correcte ou non.

De plus, si la structure est lourdement remplie, l’affectation pourrait faire en sorte que le compilateur émette quelque chose de plus efficace, car il n’a pas besoin de copier le remplissage (et il sait où il se trouve), mais mempcy() le nombre exact d’octets que vous lui demandez de copier.

Si votre chaîne est un tableau réel, à savoir:

 struct { char ssortingng[32]; size_t len; } a, b; strcpy(a.ssortingng, "hello"); a.len = strlen(a.ssortingng); 

Ensuite, vous pouvez toujours utiliser l’affectation simple:

 b = a; 

Pour obtenir une copie complète Cependant, pour les données de longueur variable modélisées comme celle-ci, ce n’est pas le moyen le plus efficace de faire la copie car le tableau entier sera toujours copié.

Attention cependant, la copie de structures contenant des pointeurs sur de la mémoire allouée au tas peut être un peu dangereuse, car ce faisant, vous alias le pointeur et le rend généralement ambiguë à qui appartient le pointeur après l’opération de copie.

Pour ces situations, une “copie profonde” est vraiment le seul choix, et cela doit aller dans une fonction.

Depuis C90, vous pouvez simplement utiliser:

 dest_struct = source_struct; 

tant que la chaîne est mémorisée dans un tableau:

 struct xxx { char theSsortingng[100]; }; 

Sinon, si c’est un pointeur, vous devrez le copier à la main.

 struct xxx { char* theSsortingng; }; dest_struct = source_struct; dest_struct.theSsortingng = malloc(strlen(source_struct.theSsortingng) + 1); strcpy(dest_struct.theSsortingng, source_struct.theSsortingng); 

Si les structures sont de types compatibles, oui, vous pouvez, avec quelque chose comme:

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

La seule chose dont vous devez être conscient est qu’il s’agit d’une copie superficielle . En d’autres termes, si vous avez un caractère char * pointant sur une chaîne spécifique, les deux structures indiqueront la même chaîne.

Et changer le contenu de l’un de ces champs de chaîne (les données sur lesquelles le caractère char * pointe, pas le caractère lui-même) changera également l’autre.

Si vous voulez une copie facile sans avoir à faire manuellement chaque champ, mais avec le bonus supplémentaire de copies de chaîne non superficielles, utilisez strdup :

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

Cela copiera tout le contenu de la structure, puis copiera en profondeur la chaîne, donnant ainsi une chaîne distincte à chaque structure.

Et si votre implémentation C n’a pas de strdup (cela ne fait pas partie de la norme ISO), obtenez-en un ici .

Vous pouvez memcpy structures, ou vous pouvez simplement les atsortingbuer comme n’importe quelle autre valeur.

 struct {int a, b;} c, d; ca = cb = 10; d = c; 
  1. Vous pouvez utiliser une structure pour lire l’écriture dans un fichier. Vous n’avez pas besoin de le lancer en tant que `char *. La taille de la structure sera également préservée. (Ce point n’est pas le plus proche du sujet mais devinez-le: le comportement sur la mémoire dure est souvent similaire à celui de la mémoire vive.)

  2. Pour déplacer (vers et depuis) ​​un seul champ de chaîne, vous devez utiliser strncpy et un tampon de chaîne transitoire '\0' terminant. Quelque part, vous devez vous souvenir de la longueur du champ de chaîne d’enregistrement.

  3. Pour déplacer d’autres champs, vous pouvez utiliser la notation par points, ex .: NodeB->one=intvar; floatvar2=(NodeA->insidebisnode_subvar).myfl;

     struct mynode { int one; int two; char txt3[3]; struct{char txt2[6];}txt2fi; struct insidenode{ char txt[8]; long int myl; void * mypointer; size_t myst; long long myll; } insidenode_subvar; struct insidebisnode{ float myfl; } insidebisnode_subvar; } mynode_subvar; typedef struct mynode* Node; ...(main) Node NodeA=malloc... Node NodeB=malloc... 
  4. Vous pouvez intégrer chaque chaîne dans une structure qui lui convient, pour éviter le point 2 et se comporter comme Cobol: NodeB->txt2fi=NodeA->txt2fi … mais vous aurez toujours besoin d’une chaîne transitoire plus une strncpy comme indiqué au point -2 pour scanf , printf sinon un opérateur plus long input (plus court), ne serait pas tronqué (par des espaces remplis).

  5. (NodeB->insidenode_subvar).mypointer=(NodeA->insidenode_subvar).mypointer va créer un alias de pointeur.
  6. NodeB.txt3=NodeA.txt3 provoque le rejet par le compilateur: error: incompatible types when assigning to type 'char[3]' from type 'char *'
  7. point-4 ne fonctionne que parce que NodeB->txt2fi & NodeA->txt2fi appartiennent au même typedef !!

    Une réponse correcte et simple à ce sujet que j’ai trouvé dans In C, pourquoi ne puis-je pas atsortingbuer une chaîne à un tableau de caractères après sa déclaration? “Les tableaux (également des caractères) sont des citoyens de deuxième classe en C” !!!