Comment comparer deux instances de structs pour l'égalité en C standard ?
Réponses
Trop de publicités?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).
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
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.
@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 avecmemset
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 ?
- Réponses précédentes
- Plus de réponses