209 votes

Comment comparer des structs pour l'égalité en C ?

Comment comparer deux instances de structs pour l'égalité en C standard ?

190voto

Greg Hewgill Points 356191

Le langage C ne fournit aucun moyen de le faire - vous devez le faire vous-même et comparer chaque structure membre par membre.

108voto

Sufian Points 3151

Vous pouvez être tenté d'utiliser memcmp(&a, &b, sizeof(struct foo)) mais cela peut ne pas fonctionner dans toutes les situations. Le compilateur peut ajouter un espace tampon d'alignement à une structure, et les valeurs trouvées aux emplacements mémoire situés dans l'espace tampon ne sont pas garanties comme étant une valeur particulière.

Mais, si vous utilisez calloc o memset la taille complète des structures avant de les utiliser, vous peut faire un peu profond comparaison avec memcmp (si votre structure contient des pointeurs, elle ne correspondra que si l'adresse vers laquelle pointent les pointeurs est la même).

22voto

Ben Points 934

Si vous le faites souvent, je vous suggère d'écrire une fonction qui compare les deux structures. De cette façon, si vous changez la structure, vous ne devrez modifier la comparaison qu'à un seul endroit.

Pour ce qui est de la manière de le faire, .... Vous devez comparer chaque élément individuellement

20voto

Vous ne pouvez pas utiliser memcmp pour comparer des structs pour l'égalité en raison des caractères de remplissage aléatoires potentiels entre les champs dans les structs.

  // bad
  memcmp(&struct1, &struct2, sizeof(struct1));

La méthode ci-dessus échouerait pour une structure comme celle-ci :

typedef struct Foo {
  char a;
  /* padding */
  double d;
  /* padding */
  char e;
  /* padding */
  int f;
} Foo ;

Vous devez utiliser la comparaison entre membres pour être sûr.

9voto

Demetri Points 715

@Greg a raison de dire qu'il faut écrire des fonctions de comparaison explicites dans le cas général.

Il est possible d'utiliser memcmp si :

  • les structs ne contiennent pas de champs à virgule flottante susceptibles d'être NaN .
  • les structs ne contiennent pas de remplissage (utiliser -Wpadded avec clang pour vérifier ceci) OU les structs sont explicitement initialisés avec memset lors de l'initialisation.
  • il n'y a pas de types de membres (tels que Windows BOOL ) qui ont des valeurs distinctes mais équivalentes.

À moins que vous ne programmiez pour des systèmes embarqués (ou que vous n'écriviez une bibliothèque susceptible d'être utilisée sur ces systèmes), je ne m'inquiéterais pas de certains cas particuliers de la norme C. La distinction entre pointeur proche et pointeur lointain n'existe sur aucun périphérique 32 ou 64 bits. Aucun système non-intégré que je connaisse n'a de pointeurs multiples. NULL les pointeurs.

Une autre option consiste à générer automatiquement les fonctions d'égalité. Si vous disposez vos définitions de structures de manière simple, il est possible d'utiliser un traitement de texte simple pour gérer les définitions de structures simples. Vous pouvez utiliser libclang pour le cas général - puisqu'il utilise le même frontal que Clang, il gère tous les cas de figure correctement (sauf bogues).

Je n'ai pas vu une telle bibliothèque de génération de code. Cependant, elle semble relativement simple.

Cependant, il est également vrai que ces fonctions d'égalité générées feraient souvent la mauvaise chose au niveau de l'application. Par exemple, si deux UNICODE_STRING Dans Windows, les structs sont comparés de manière superficielle ou profonde ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X