taille d’une structure contenant des champs de bits

Dupliquer possible:
Pourquoi sizeof pour un struct n’est-il pas égal à la sum de sizeof de chaque membre?

J’essayais de comprendre le concept de champs de bits. Mais je ne suis pas capable de trouver pourquoi la taille de la structure suivante dans CASE III est de 8 octets.

CAS I:

struct B { unsigned char c; // +8 bits } b; 

taille de (b); // Sortie: 1 (car le caractère non signé prend 1 octet sur mon système)

CAS II:

 struct B { unsigned b: 1; } b; sizeof(b); // Output: 4 (because unsigned takes 4 bytes on my system) 

CAS III:

 struct B { unsigned char c; // +8 bits unsigned b: 1; // +1 bit } b; sizeof(b); // Output: 8 

Je ne comprends pas pourquoi la sortie du cas III est 8. Je m’attendais à 1 (caractère) + 4 (non signé) = 5.

Vous pouvez vérifier la mise en page de la structure en utilisant offsetof , mais ce sera un peu comme suit:

 struct B { unsigned char c; // +8 bits unsigned char pad[3]; //padding unsigned int bint; //your b:1 will be the first byte of this one } b; 

Maintenant, il est évident que (dans une archive 32 bits), la sizeof(b) sera 8 , n’est-ce pas?

La question est, pourquoi 3 octets de remplissage, et pas plus ou moins?

La réponse est que le décalage d’un champ dans une structure a les mêmes exigences d’alignement que le type du champ lui-même. Dans votre architecture, les entiers sont alignés sur 4 octets. Ainsi, offsetof(b, bint) doit être multiple de 4. Il ne peut pas être 0, car il y a le c précédent, il sera donc 4. Si champ bint commence à offset 4 et fait 4 octets de long, la taille de la structure est 8.

Une autre façon de voir les choses est que l’exigence d’alignement d’une structure est le plus grand de ses champs. Ce B sera donc aligné sur 4 octets (puisqu’il s’agit de votre champ de bits). Mais la taille d’un type doit être un multiple de l’alignement, 4 n’est pas suffisant, il sera donc 8.

Je pense que vous voyez un effet d’ alignement ici.

De nombreuses architectures exigent que des entiers soient stockés à des adresses en mémoire multiples de la taille du mot.

C’est pourquoi le caractère de votre troisième structure est complété avec trois octets supplémentaires, de sorte que le nombre entier non signé suivant commence à une adresse qui est un multiple de la taille du mot.

Les caractères sont par définition un octet. Les ints sont 4 octets sur un système 32 bits. Et la structure est en cours de rembourrage supplémentaire 4.

Voir http://en.wikipedia.org/wiki/Data_structure_alignment#Typical_alignment_of_C_structs_on_x86 pour une explication du remplissage

Pour que les access à la mémoire restnt alignés, le compilateur ajoute du rembourrage. Si vous compressez la structure, il ne sera pas ajouté.

J’ai jeté un autre coup d’oeil à ceci et voici ce que j’ai trouvé.

  1. Dans le livre C, “presque tout ce qui concerne les champs dépend de la mise en oeuvre”.
  2. Sur ma machine:
  struct B { unsigned c: 8; unsigned b: 1; }b; printf("%lu\n", sizeof(b)); 

print 4 qui est un court;

Vous mélangiez des champs de bits avec des éléments de structure réguliers

BTW, un champ de bits est défini comme: “un ensemble de bits adjacents dans une unité de stockage définie par une implémentation sindle”. Par conséquent, je ne suis même pas sûr que le ‘: 8’ fasse ce que vous voulez. Cela ne semble pas être dans l’esprit des champs de bits (car ce n’est plus un peu)

L’alignement et la taille totale de la structure dépendent de la plate-forme et du compilateur. Vous ne pouvez pas vous attendre à des réponses directes et prévisibles ici. Le compilateur peut toujours avoir une idée spéciale. Par exemple:

 struct B { unsigned b0: 1; // +1 bit unsigned char c; // +8 bits unsigned b1: 1; // +1 bit }; 

Le compilateur peut fusionner les champs b0 et b1 dans un entier et ne le peut pas. C’est au compilateur. Certains compilateurs ont des clés de ligne de commande qui contrôlent cela, d’autres non. Autre exemple:

 struct B { unsigned short c, d, e; }; 

Il appartient au compilateur de compresser / ne pas compresser les champs de cette structure (plate-forme 32 bits). La disposition de la structure peut différer entre les versions DEBUG et RELEASE.

Je recommanderais d’utiliser uniquement le modèle suivant:

 struct B { unsigned b0: 1; unsigned b1: 7; unsigned b2: 2; }; 

Lorsque vous avez une séquence de champs de bits qui partagent le même type, le compilateur les mettra dans un seul int. Sinon, différents aspects peuvent entrer en jeu. Tenez également compte du fait que dans un grand projet, vous écrivez un morceau de code et que quelqu’un d’autre écrit et réécrit le fichier Make; déplacez votre code d’une DLL à une autre. À ce stade, les indicateurs du compilateur seront définis et modifiés. 99% de chances que ces personnes n’aient aucune idée des exigences d’alignement pour votre structure. Ils n’ouvriront même jamais votre dossier.