Copia di una struttura in un’altra

So che posso copiare il membro della struttura per membro, invece di quello posso fare una memcpy sulle strutture?

È consigliabile farlo?

Nella mia struttura, ho una stringa anche come membro che devo copiare in un’altra struttura con lo stesso membro. Come lo faccio?

La copia per semplice compito è la migliore, dal momento che è più breve, più facile da leggere e ha un livello più alto di astrazione. Invece di dire (al lettore umano del codice) “copia questi bit da qui a lì”, e chiedendo al lettore di pensare all’argomento delle dimensioni della copia, stai semplicemente facendo un semplice compito (“copia questo valore da qui a qui “). Non ci può essere alcuna esitazione sul fatto che la dimensione sia corretta o meno.

Inoltre, se la struttura è pesantemente riempita, l’assegnazione potrebbe far sì che il compilatore emetta qualcosa di più efficiente, poiché non deve copiare il padding (e sa dove si trova), ma mempcy() non lo fa così copierà sempre il numero esatto di byte che gli dici di copiare.

Se la tua stringa è una matrice reale, cioè:

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

Quindi puoi ancora usare un compito semplice:

 b = a; 

Per ottenere una copia completa. Tuttavia, per dati a lunghezza variabile modellati come questo, questo non è il modo più efficiente di eseguire la copia poiché l’intero array verrà sempre copiato.

Fate attenzione, tuttavia, che copiare le strutture che contengono i puntatori alla memoria allocata all’heap può essere un po ‘pericoloso, poiché in questo modo si esegue il puntamento alias del puntatore e in genere si rende ambiguo chi possiede il puntatore dopo l’operazione di copia.

Per queste situazioni una “copia profonda” è davvero l’unica scelta, e questo deve andare in una funzione.

Dalla C90, puoi semplicemente usare:

 dest_struct = source_struct; 

finché la stringa è memorizzata all’interno di un array:

 struct xxx { char theString[100]; }; 

Altrimenti, se si tratta di un puntatore, dovrai copiarlo a mano.

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

Se le strutture sono di tipi compatibili, sì, puoi, con qualcosa di simile:

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

L’unica cosa di cui devi essere a conoscenza è che questa è una copia superficiale . In altre parole, se si dispone di un char * punta a una stringa specifica, entrambe le strutture punteranno alla stessa stringa.

E cambiando il contenuto di uno di quei campi stringa (i dati a cui punta il char * , non il char * stesso) cambieranno anche l’altro.

Se si desidera una copia semplice senza dover eseguire manualmente ciascun campo ma con il vantaggio aggiuntivo di copie di stringa non superficiali, utilizzare strdup :

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

Ciò copierà l’intero contenuto della struttura, quindi copierà in profondità la stringa, fornendo effettivamente una stringa separata a ciascuna struttura.

E, se la tua implementazione C non ha un strdup (non fa parte dello standard ISO), strdup uno da qui .

Puoi memcpy structs, o puoi semplicemente assegnarli come qualsiasi altro valore.

 struct {int a, b;} c, d; ca = cb = 10; d = c; 
  1. Puoi usare una struct per leggere la scrittura in un file. Non è necessario eseguire il cast come `char *. Anche la dimensione della struttura verrà preservata. (Questo punto non è il più vicino all’argomento, ma immaginalo: comportarsi su una memoria rigida è spesso simile a quello della RAM.)

  2. Per spostare (verso e da) un campo di stringa singola, è necessario utilizzare strncpy e un buffer di stringa temporaneo '\0' termina. Da qualche parte devi ricordare la lunghezza del campo della stringa del record.

  3. Per spostare altri campi puoi usare la notazione a punti, es .: 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. Puoi incorporare ogni stringa in una struttura che gli si adatta, per eludere il punto 2 e comportarti come Cobol: NodeB->txt2fi=NodeA->txt2fi … ma avrai comunque bisogno di una stringa transitoria più una strncpy come menzionato al punto -2 per scanf , printf altrimenti un operatore con input più lungo (più corto), non sarebbe stato troncato (da spazi riempiti).

  5. (NodeB->insidenode_subvar).mypointer=(NodeA->insidenode_subvar).mypointer creerà un alias del puntatore.
  6. NodeB.txt3=NodeA.txt3 respinge il compilatore: error: incompatible types when assigning to type 'char[3]' from type 'char *'
  7. point-4 funziona solo perché NodeB->txt2fi e NodeA->txt2fi appartengono allo stesso typedef !!

    Una risposta corretta e semplice a questo argomento che ho trovato in In C, perché non posso assegnare una stringa a un array di caratteri dopo che è stata dichiarata? “Gli array (anche di chars) sono cittadini di seconda class in C” !!!