Structure de copie en C avec assignation au lieu de memcpy()

jusqu'à récemment, je n'ai vu que la copie des champs de structure faite avec memcpy(). Dans les classes et les instructions en ligne, copier le contenu d'une structure dans une autre ressemble généralement à

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 */

cependant, cette tâche peut aussi être accomplie par une simple tâche remplaçant le memcpy().

*b1 = *b0; /* dereferenced struct assignment */

y a-t-il une bonne raison pour que cela ne soit pas aussi largement utilisé (du moins dans mon expérience limitée)? Est-ce que ces deux méthodes-assignation et memcpy()-l'équivalent, ou est il une raison impérieuse d'utiliser memcpy() en général?

19
demandé sur olliezhu 2012-11-08 10:57:43

5 réponses

les deux méthodes sont équivalentes, et effectuent un copie. Cela signifie que la structure elle-même est copiée, mais tout ce que la structure renvoie n'est pas copié.

pourquoi memcpy est plus populaire, Je ne suis pas sûr. Les versions plus anciennes de C ne supportaient pas l'assignation de structure ( bien qu'il s'agisse d'une extension courante dès 1978), alors peut-être le style memcpy collé comme un moyen de faire plus de code portable? Dans tous les cas, l'attribution de la structure est largement soutenu dans les compilateurs de PC, et en utilisant memcpy est plus sujet aux erreurs (si vous vous trompez de taille, de mauvaises choses sont susceptibles de se produire), et il est donc préférable d'utiliser l'assignation de structure lorsque cela est possible.

Il y a cependant des cas où seulement memcpy fonctionne. Par exemple:

  • si vous copiez une structure vers ou depuis un tampon non aligné-par exemple, pour sauvegarder/charger vers / depuis un disque ou envoyer / recevoir sur un réseau - vous devez utiliser memcpy, car l'attribution de la structure nécessite à la fois la source et la destination doivent être alignées correctement.
  • Si vous êtes d'emballage information supplémentaire après une structure, peut-être utilisant un tableau à zéro élément, vous devez utiliser memcpy, et introduisez cette information supplémentaire dans le champ Taille.
  • si vous copiez un tableau de structures, il être plus efficace pour faire un seul memcpy plutôt que de faire une boucle et de copier les structures individuellement. Puis de nouveau, il ne peut pas. C'est difficile à dire, memcpy implémentations diffèrent dans leurs caractéristiques de performance.
  • certains compilateurs intégrés pourraient ne pas supporter l'assignation de structure. Il y a probablement d'autres choses plus importantes que le compilateur en question ne supporte pas aussi bien, bien sûr.

Notez aussi que bien qu'en C memcpy et les assignations de structure sont généralement équivalentes, en C++ memcpy et l'affectation de la structure est équivalent. En général c++ il est préférable d'éviter memcpy ing les structures, comme l'attribution de structure peut, et est souvent, surchargé pour faire des choses supplémentaires telles que des copies profondes ou la gestion du compte de référence.

28
répondu bdonlan 2012-11-08 07:12:53

ce n'est pas la réponse exacte que vous cherchez.

j'explique le scénario que j'ai rencontré.

quand on utilise memcpy(), il ne octet-par-octet copie de destination. ne vous inquiétez donc pas de l'alignement des données dans L'architecture ARM. Si vous utilisez = opérateur, et tout l'un de l'adresse n'est pas aligné sur 4 octets alors l'alignement faute viendra.

Depuis le Bras site:

un pointeur vers l'emplacement de destination qui est un byte au-delà le dernier octet écrit à. Cela permet de poursuivre le processus d'écriture with perfect alignment of bytes pour la concaténation de chaîne de blocs de mémoire.

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0175k/Cihbbjge.html

6
répondu Jeyaram 2012-11-08 07:26:17

je ressuscite cette vieille question parce que les réponses n'expliquent pas pourquoimemcpy est en fait préférable.

memcpy est préféré, car il est clair que le programmeur veut copier le contenu et non pas simplement les pointeurs.

Dans l'exemple suivant, les deux affectations de faire deux choses très différentes:

struct Type *s1,*s2;
*s1=*s2;
s1=s2;

L'utilisation par inadvertance de l'un au lieu de l'autre peut avoir des effets désastreux. Le compilateur n'a pas à se plaindre. Sauf le programme se bloque lorsqu'un pointeur non initialisé est utilisé, l'erreur peut passer inaperçue pendant une longue période et produire des effets secondaires étranges.

Écrit comme:

memcpy(s1,s2,sizeof(*s1));
memcpy(s1,s2,sizeof(*s2));
memcpy(s1,s2,sizeof(struct Type));

faire savoir au lecteur que l'intention est de copier le contenu (au détriment de la sécurité de type et la vérification des limites).

certains compilateurs (gcc par exemple) émettent même un avertissement sur la taille quand ils rencontrent quelque chose comme:

memcpy(s1,s2,sizeof(s1));
3
répondu Frédéric Marchal 2016-01-06 09:13:07

certaines personnes préfèrent memcpy parce que c'est ce qu'ils ont appris et ils n'ont jamais compris qu'ils pouvaient juste faire une tâche (dans les temps anciens la tâche n'était pas autorisée, mais c'est il y a longtemps). Il n'y a pas de problèmes d'alignement à résoudre puisque la mémoire allouée par malloc () est toujours alignée correctement. Et puisqu'un compilateur pourrait trivialement traduire cette tâche en un appel memcpy, il ne serait jamais plus lent ou plus de code que memcpy. Bien sûr, il existe des systèmes embarqués avec des compilateurs obsolètes.

0
répondu gnasher729 2014-03-31 14:18:29

les personnes qui travaillent sur une plate-forme intégrée préféreront utiliser la memcopie plutôt que l'assignation directe de la structure . Principalement lorsque vous traitez avec la plate-forme intégrée, certains compilateurs ne supporte pas l'assignation directe de structure, pour que vous ayez besoin d'utiliser la memcopie. si vous travaillez sur ordinateur, alors il n'y a pas de problème dans les deux cas, les Deux sont valables.

-2
répondu Tushar Kanani 2012-11-08 07:07:36