web-dev-qa-db-fra.com

Existe-t-il des raisons d'éviter les membres de la structure de champs de bits?

Je savais depuis longtemps qu'il y a des champs de bits en C et je les utilise parfois pour définir des structures densément compactes:

typedef struct Message_s {
     unsigned int flag : 1;
     unsigned int channel : 4;
     unsigned int signal : 11;
} Message;

Lorsque je lis du code source ouvert, je trouve souvent des masques de bits et des opérations de décalage de bits pour stocker et récupérer de telles informations dans des champs de bits roulés à la main. C’est tellement courant que je ne pense pas que les auteurs ne connaissaient pas la syntaxe des champs de bits. Je me demande donc s’il existe des raisons de faire rouler les champs de bits via des masques binaires et de décaler vos propres opérations au lieu de vous fier au compilateur code pour obtenir et définir de tels champs de bits.

18
wirrbel

Pourquoi d'autres programmeurs utilisent-ils des manipulations de bits codées manuellement au lieu de champs de bits pour regrouper plusieurs champs dans un seul mot?

Cette réponse est basée sur une opinion car la question est assez ouverte:

  • De nombreux programmeurs ignorent la disponibilité des champs de bits ou ne sont pas certains de leur portabilité et de leur sémantique précise. Certains se méfient même de la capacité du compilateur à produire le code correct. Ils préfèrent écrire du code explicite qu'ils comprennent.

    Comme l'a expliqué Cornstalks, cette attitude est ancrée dans l'expérience de la vie réelle comme l'explique cet article .

  • La structure mémoire réelle de Bitfield est définie par l'implémentation: si la structure mémoire doit suivre une spécification précise, les champs de bits ne doivent pas être utilisés et des manipulations de bits codées à la main peuvent être nécessaires.
  • La gestion des valeurs signées dans des champs de bits typés signés est définie par l'implémentation. Si les valeurs signées sont regroupées dans une plage de bits, il peut être plus fiable de coder à la main les fonctions d'accès.
15
chqrlie

Y a-t-il des raisons d'éviter les structures de champs?

bitfield-structs a quelques limitations:

  1. Les champs de bits génèrent un code non portable. De plus, la longueur du champ de bits dépend fortement de la taille de Word.
  2. La lecture (à l'aide de scanf()) et l'utilisation de pointeurs sur des champs de bits n'est pas possible en raison de la non-adressabilité.
  3. Les champs de bits sont utilisés pour intégrer davantage de variables dans un espace de données réduit, mais le compilateur génère un code supplémentaire pour manipuler ces variables. Cela se traduit par une augmentation des complexités spatiales et temporelles.
  4. L'opérateur sizeof() ne peut pas être appliqué aux champs de bits, car sizeof() renvoie le résultat en octets et non en bits.

La source

Donc, si vous devez les utiliser ou non dépend. Lire la suite dans Pourquoi l’endianité des bits est un problème dans les champs de bits?


PS: Quand utiliser les champs de bits en C?

8
gsamaras

Il n'y a aucune raison pour cela. Les champs de bits sont utiles et pratiques. Ils sont d'usage courant dans les projets intégrés. Certaines architectures (comme ARM) ont même des instructions spéciales pour manipuler les champs de bits. 

Comparez simplement le code (et écrivez le reste de la fonction foo1) https://godbolt.org/g/72b3vY

4
P__J__

Dans de nombreux cas, il est utile de pouvoir traiter des groupes de bits individuels dans un mot ou d’opérer sur un mot en tant qu’unité. La norme ne fournit actuellement Aucun moyen pratique et portable d’atteindre cette fonctionnalité. Si le code est écrit pour utiliser des champs de bits et qu'il est par la suite nécessaire d'accéder à plusieurs groupes en tant que Word, il n'y aurait aucun moyen agréable de le gérer sans retravailler tout le code en utilisant les champs de bits ou en désactivant les optimisations d'alias basé sur le type, en utilisant le type punning, et en espérant que tout se déroule comme prévu.

Utiliser des décalages et des masques peut être inélégant, mais jusqu'à ce que C fournisse un moyen de traiter une séquence de bits explicitement désignés dans une lvalue comme une autre lvalue, c'est souvent le meilleur moyen de s'assurer que le code sera adaptable répondre aux besoins.

0
supercat