otra - Copiando la estructura en C con asignación en lugar de memcpy()
copiar una estructura a otra en c (5)
Hasta hace poco, solo he visto la copia de los campos de estructura realizados con memcpy()
. En las clases e instrucciones en línea, copiar el contenido de una estructura en otra generalmente se ve como
struct block *b0 = malloc(sizeof(struct block));
struct block *b1 = malloc(sizeof(struct block));
/* populate fields in *b0 */
memcpy(b1, b0, sizeof *b1); /* copy contents of b0 into b1 */
/* free b0, b1 */
Sin embargo, esta tarea también se puede llevar a cabo mediante una tarea simple que reemplaza a memcpy()
.
*b1 = *b0; /* dereferenced struct assignment */
¿Hay alguna buena razón por la que esto no se usa tanto (al menos en mi experiencia limitada)? ¿Son estos dos métodos, asignación y memcpy()
, equivalentes, o hay alguna razón convincente para usar memcpy()
en general?
Algunas personas prefieren memcpy porque eso es lo que aprendieron y nunca se dieron cuenta de que solo podían hacer una tarea (en la antigüedad no se permitía la tarea, pero eso era hace mucho tiempo). No hay problemas de alineación de los que preocuparse ya que la memoria asignada por malloc () siempre está alineada correctamente. Y como un compilador podría traducir de forma trivial esta asignación a una llamada memcpy, nunca sería más lento o más codigo que memcpy. Por supuesto, hay sistemas embebidos con compiladores obsoletos.
Ambos métodos son equivalentes, y realizan una copia superficial . Esto significa que la estructura en sí se copia, pero todo lo que la estructura hace referencia no se copia.
En cuanto a por qué memcpy
es más popular, no estoy seguro. Las versiones anteriores de C no admitían la asignación de estructuras ( aunque era una extensión común desde 1978 ), ¿quizás el estilo memcpy se atasque como una forma de hacer más código portátil? En cualquier caso, la asignación de estructura es ampliamente compatible con los compiladores de PC, y usar memcpy
es más propenso a errores (si el tamaño es incorrecto, es probable que ocurran cosas malas), por lo que es mejor usar la asignación de estructura siempre que sea posible.
Hay, sin embargo, casos en los que solo funciona memcpy
. Por ejemplo:
- Si está copiando una estructura ao desde un búfer no alineado (p. Ej., Para guardar / cargar en / desde el disco o enviar / recibir en una red), necesita usar
memcpy
, ya que la asignación de la estructura requiere que la fuente y el destino estén alineados correctamente . - Si está empaquetando información adicional después de una estructura, tal vez utilizando una matriz de cero elementos , necesita usar
memcpy
y factorizar esta información adicional en el campo de tamaño. - Si está copiando una matriz de estructuras, puede ser más eficiente hacer un solo
memcpy
lugar de hacer un bucle y copiar las estructuras individualmente. Por otra parte, puede que no. Es difícil decirlo,memcpy
implementaciones dememcpy
difieren en sus características de rendimiento. - Es posible que algunos compiladores incrustados no admitan la asignación de estructuras. Es probable que haya otras cosas más importantes que el compilador en cuestión no soporta también, por supuesto.
Tenga en cuenta también que aunque en C memcpy
y la asignación de estructuras son generalmente equivalentes, en C ++ memcpy
y la asignación de estructuras no son equivalentes. En general, C ++ es mejor evitar las estructuras de memcpy
, ya que la asignación de estructura puede, y con frecuencia se sobrecarga, hacer cosas adicionales, como copias en profundidad o gestión de recuento de referencias.
Esta no podría ser la respuesta exacta que estás buscando.
Estoy explicando el escenario que conocí.
cuando usamos memcpy()
, se realiza una copia byte a byte al destino. así que no se preocupe por la alineación de datos en la arquitectura ARM. Si utiliza el operador =
, y cualquiera de las direcciones no está alineada con 4 bytes, se producirá un error de alineación.
Desde el sitio del brazo:
Un puntero a la ubicación de destino que es un byte más allá del último byte escrito. Esto permite la continuación del proceso de escritura with perfect alignment of bytes
para la concatenación de cadenas de bloques de memoria.
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0175k/Cihbbjge.html
Estoy resucitando esta vieja pregunta porque las respuestas no explican por memcpy
se prefiere realmente memcpy
.
Se prefiere memcpy
porque deja en claro que el programador desea copiar el contenido y no simplemente los punteros.
En el siguiente ejemplo, las dos tareas hacen dos cosas muy diferentes:
struct Type *s1,*s2;
*s1=*s2;
s1=s2;
El uso inadvertido de uno en lugar del otro puede tener efectos desastrosos. El compilador no se quejará. A menos que el programa se bloquee cuando se usa un puntero sin inicializar, el error puede pasar inadvertido durante mucho tiempo y producir efectos secundarios extraños.
Escribiéndolo como uno de:
memcpy(s1,s2,sizeof(*s1));
memcpy(s1,s2,sizeof(*s2));
memcpy(s1,s2,sizeof(struct Type));
deje que el lector sepa que la intención es copiar el contenido (a expensas de la seguridad del tipo y la verificación de límites).
Algunos compiladores (por ejemplo, gcc) emiten una advertencia sobre el tamaño cuando encuentran algo como:
memcpy(s1,s2,sizeof(s1));
Las personas que trabajan en plataformas integradas preferirán usar memcopy en lugar de la asignación directa de estructura. Principalmente cuando se trata de plataformas integradas, algunos compiladores no admiten la asignación de estructura directa, por lo que necesita usar memcopy. Si está trabajando en PC, entonces no hay problema en ninguno de los dos casos, ambos son válidos.