2016-10-14 1 views
0

J'utilise une grande structure avec beaucoup de membres, et je voudrais un moyen facile de voir rapidement si l'un des membres est différent de zéro. Je sais que memcmp() ne devrait pas être utilisé pour comparer deux structures pour l'égalité (comme expliqué ici: How do you compare structs for equality in C?), mais j'espère qu'en comparant une structure à un bloc de mémoire qui a été mis à 0, cela peut fonctionner.Puis-je utiliser memcmp pour vérifier la structure pour les membres non nuls?

Par exemple, supposons que j'ai quelques struct:

typedef struct { 
    int Int1; 
    int Int2; 
    int Int3; 
} MyInts; 

Je crée une variable de cette structure:

MyInts MyStruct = {0}; 

Tout au long de l'exécution de mon programme, les membres de MyStruct seront généralement 0, mais peut parfois être mis à une valeur non nulle temporairement. Je veux vérifier rapidement si l'un des nombres de MyStruct est différent de zéro. Puis-je utiliser memcmp() comme ci-dessous?

// Create empty struct to test against 
MyInts EmptyStruct = {0}; 

// Make sure entire memory block of test struct is cleared 
memset(&EmptyStruct, 0, sizeof(MyInts)); 

// Compare MyStruct to EmptyStruct to see if any non-zero members exist 
int result = memcmp(&MyStruct, &EmptyStruct, sizeof(MyInts)); 
+0

Remarque: 'double fn = -0,0; fp = 0.0; '->' fn == fp', les deux sont égaux à zéro. Pourtant 'memcmp (& fp, & fn, sizeof fp)' signale la différence. – chux

+0

Ne pas thnk 'MyInts EmptyStruct = {0};' est spécifié pour initialiser le remplissage à zéro bits. – chux

+1

@chux il est garanti de régler le remplissage à zéro bits, voir C11 6.7.9/10 (et/21 qui se réfère à/10) –

Répondre

0

Vous ne pouvez pas le faire dans le cas général, car struct peuvent avoir un rembourrage entre les champs et à la fin de la struct, et le contenu des octets pad n'est pas garantie (peut-être des déchets non initialisée) .

Si les deux struct comparées ont été initialement attribués à calloc, ou avait sizeof(thestruct) octets memset à zéro avant de remplir les valeurs réelles que, le rembourrage aurait des valeurs prévisibles et memcmp fonctionnerait. De même, si vous pouvez garantir aucun rembourrage, alors ce memcmp fonctionnera. Mais si l'un d'entre eux n'a peut-être pas été mis à zéro, non, pas en sécurité. Bien sûr, si vous voulez être "gentil", vous pouvez simplement comparer les membres directement, éventuellement dans une fonction factorisée, et laisser le compilateur gérer l'optimisation, sans vous soucier si vous avez des structures non zéros avec un remplissage flottant.

Remarque: The second highest voted answer sur le lien que vous avez fourni couvre ceci. Les commentaires sur cette réponse notent également certains cas marginaux, par ex. float s peut avoir des valeurs qui se comparent égales mais qui ont des représentations de bits différentes, de sorte qu'il n'est pas généralisable à toutes les structures.

+0

Hmmm. Est-ce que le remplissage est spécifié pour être stable avec une affectation de structure comme 'a = b'? – chux

+0

Ahhh, votre commentaire est tout à fait logique. Merci pour la réponse rapide! – phreaknik

+0

Le remplissage peut ne pas être préservé par une affectation de structure (C11 6.2.6.1/6). En outre, il n'est pas clair pour moi si le rembourrage est garanti pour être préservé en assignant à des membres individuels. –

0

J'ai décidé d'aller de l'avant et de répondre à ma propre question pour plus de clarté sur la base des commentaires. Comme mentionné @ M.M, il n'est pas garanti que le remplissage soit préservé par une affectation de structure, et peut-être aussi pas conservé par une affectation de membre individuelle. Par conséquent, l'utilisation de memcmp pour vérifier une structure pour des membres non-Zéro n'est pas sûre.

Le moyen le plus sûr de le faire, comme ShadowRanger suggests, serait de comparer individuellement chaque membre struct.