Copiando una estructura a otra

Sé que puedo copiar el miembro de la estructura por miembro, en lugar de eso, ¿puedo hacer una memcpy en las estructuras?

¿Es aconsejable hacerlo?

En mi estructura, tengo una cadena también como miembro que tengo que copiar a otra estructura que tenga el mismo miembro. ¿Cómo puedo hacer eso?

La copia por asignación simple es lo mejor, ya que es más corta, más fácil de leer y tiene un mayor nivel de abstracción. En lugar de decir (al lector humano del código) “copie estos bits de aquí para allá” y requiera que el lector piense en el argumento del tamaño de la copia, simplemente está haciendo una asignación simple (“copie este valor de aquí hasta aquí “). No puede haber dudas sobre si el tamaño es correcto o no.

Además, si la estructura está muy acolchada, la asignación puede hacer que el comstackdor emita algo más eficiente, ya que no tiene que copiar el relleno (y sabe dónde está), pero mempcy() no lo hace, por lo que siempre copiará el número exacto de bytes que le dice que copie.

Si su cadena es una matriz real, es decir:

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

Entonces todavía puedes usar asignación simple:

 b = a; 

Para obtener una copia completa. Sin embargo, para los datos de longitud variable modelados así, esta no es la forma más eficiente de hacer la copia ya que toda la matriz siempre se copiará.

Sin embargo, tenga en cuenta que la copia de estructuras que contienen punteros a la memoria asignada en el montón puede ser un poco peligrosa, ya que al hacerlo se alias el puntero y, por lo general, resulta ambiguo quién posee el puntero después de la operación de copia.

Para estas situaciones, una “copia profunda” es realmente la única opción, y eso debe ir en una función.

Desde C90, puede simplemente usar:

 dest_struct = source_struct; 

siempre que la secuencia se memorice dentro de una matriz:

 struct xxx { char theString[100]; }; 

De lo contrario, si es un puntero, deberá 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); 

Si las estructuras son de tipos compatibles, sí, puedes hacerlo con algo como:

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

Lo único que debes tener en cuenta es que esta es una copia superficial . En otras palabras, si tiene un char * apuntando a una cadena específica, ambas estructuras apuntarán a la misma cadena.

Y cambiar el contenido de uno de esos campos de cadena (los datos a los que apunta el char * , no el char * mismo) también cambiarán el otro.

Si desea una copia fácil sin tener que hacer manualmente cada campo, pero con la ventaja adicional de copias de cadenas no superficiales, use strdup :

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

Esto copiará todo el contenido de la estructura, luego copie profundamente la cadena, dando efectivamente una cadena separada a cada estructura.

Y, si su implementación C no tiene un strdup (no es parte del estándar ISO), obtenga uno desde aquí .

Puede memcpy structs, o simplemente puede asignarlos como cualquier otro valor.

 struct {int a, b;} c, d; ca = cb = 10; d = c; 
  1. Puede usar una estructura para leer y escribir en un archivo. No es necesario que lo lances como un `char *. El tamaño de la estructura también se conservará. (Este punto no está más cerca del tema, pero adivinelo: comportarse en la memoria dura a menudo es similar a la memoria RAM).

  2. Para mover (hacia y desde) un único campo de cadena, debe usar strncpy y un búfer de cadena transitoria '\0' terminando. En algún lugar debe recordar la longitud del campo de cadena de registro.

  3. Para mover otros campos, puede usar la notación de puntos, por ejemplo: 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. Puede incrustar cada cadena en una estructura que se ajuste a ella, evadir el punto 2 y comportarse como Cobol: NodeB->txt2fi=NodeA->txt2fi … pero aún necesitará una cadena transitoria más una strncpy como se menciona en el punto -2 para scanf , printf contrario, una entrada más larga del operador (más corta) no se truncaría (con espacios acolchados).

  5. (NodeB->insidenode_subvar).mypointer=(NodeA->insidenode_subvar).mypointer creará un alias de puntero.
  6. NodeB.txt3=NodeA.txt3 hace que el comstackdor rechace: error: incompatible types when assigning to type 'char[3]' from type 'char *'
  7. point-4 funciona solo porque NodeB->txt2fi & NodeA->txt2fi pertenecen al mismo typedef !!

    Una respuesta correcta y simple a este tema que encontré en In C, ¿por qué no puedo asignar una cadena a una matriz de caracteres una vez que se ha declarado? “Las matrices (también de caracteres) son ciudadanos de segunda clase en C”.