web-dev-qa-db-fra.com

Comment la taille d'une structure avec des champs binaires est-elle déterminée / mesurée?

#include <stdio.h>

typedef struct size
{
        unsigned int a:1;
        unsigned int b:31;
        unsigned int c:1;
} mystruct;

int main()
{
        mystruct a;
        printf("%d", sizeof(a));
        return 0;
}
  • Avec int b:31, la sortie est 8.
  • Avec int b:1, la sortie est 4.
  • Avec int b:32, la sortie est 12.

Quelqu'un peut-il expliquer la raison de cela?

38
Jagan

Vous ne dites pas si vous savez ce que sont les champs de bits, mais je suppose que oui.

Sur votre implémentation, évidemment unsigned int est un entier de 32 bits, occupant 4 octets. Cela représente les premier et deuxième exemples. Il est clair que 3 champs binaires totalisant 33 bits ne rentrent pas dans un seul unsigned int, d'où la nécessité de 8 octets dans le premier exemple. 3 champs binaires totalisant 3 bits correspondent certainement à un unsigned int, donc seulement 4 octets dans le deuxième exemple.

De plus, un champ de bits ne peut pas s'étendre sur plusieurs entiers. Cela représente le troisième exemple. Je ne me souviens pas si c'est une exigence de la norme, ou juste un détail de votre implémentation. Quoi qu'il en soit, puisque b est de 32 bits, il remplit un entier unsigned int seul, forçant à la fois a et c à occuper leur propre unsigned int, avant et après celui du milieu. Par conséquent, 12 octets.

29
Steve Jessop

C'est l'ordre qui compte. Le code suivant donnera la sortie: 8

#include<stdio.h>

typedef struct size
{
        unsigned int b:32;
        unsigned int a:1;
        unsigned int c:1;
}mystruct;

int main(int argc, char const *argv[])
{
        mystruct a;
        printf("\n %lu \n",sizeof(a));
        return 0;
}

Un entier non signé est un entier de 32 bits, occupant 4 octets. La mémoire est allouée de manière contiguë en mémoire.


Option 1:

unsigned int a:1;       // First 4 bytes are allocated
unsigned int b:31;      // Will get accomodated in the First 4 bytes
unsigned int c:1;       // Second 4 bytes are allocated

Sortie: 8


Option 2:

unsigned int a:1;       // First 4 bytes are allocated
unsigned int b:32;      // Will NOT get accomodated in the First 4 bytes, Second 4 bytes are allocated
unsigned int c:1;       // Will NOT get accomodated in the Second 4 bytes, Third 4 bytes are allocated

Sortie: 12


Option 3:

unsigned int a:1;       // First 4 bytes are allocated
unsigned int b:1;       // Will get accomodated in the First 4 bytes
unsigned int c:1;       // Will get accomodated in the First 4 bytes

Sortie: 4


Option 4:

unsigned int b:32;      // First 4 bytes are allocated
unsigned int a:1;       // Second 4 bytes are allocated
unsigned int c:1;       // Will get accomodated in the Second 4 bytes

Sortie: 8

44
MdT

Alignement

Le compilateur arrondit la taille de la structure à 32 bits, la taille de chaque objet qu'il peut essayer de référencer à 32 bits, et en même temps, il préserve l'ordre de vos champs de bits.

Donc, si vous avez un élément 32 bits au milieu et des éléments 1 bit de chaque côté, c'est 3 mots 32 bits à allouer et donc: 12 octets.

Pour les deux autres cas, il s'agit simplement de savoir dans combien d'objets 32 bits votre séquence de champs binaires peut être compressée, tout en préservant l'ordre des champs.

10
DigitalRoss

Selon réponse de Steve Jessop juste pour répondre à sa réponse en ajoutant quelques documents qui peuvent aider.

Un membre d'une structure ou d'une union peut avoir tout type d'objet complet autre qu'un type modifié de manière variable. En outre, un membre peut être déclaré composé d'un nombre spécifié de bits (y compris un bit de signe, le cas échéant). Un tel membre est appelé un champ de bits sa largeur est précédée de deux points

Une implémentation peut allouer n'importe quelle unité de stockage adressable suffisamment grande pour contenir un champ binaire. S'il reste suffisamment d'espace, un champ binaire qui suit immédiatement un autre champ binaire dans une structure doit être compressé en bits adjacents de la même unité. S'il reste un espace insuffisant, si un champ binaire qui ne correspond pas est placé dans l'unité suivante ou chevauche des unités adjacentes est défini par l'implémentation. L'ordre d'allocation des champs binaires dans une unité ( de haut en bas ou de bas en haut) est défini par l'implémentation. L'alignement de l'unité de stockage adressable n'est pas spécifié.

Dans un objet de structure, les membres non-champ de bits et les unités dans lesquelles résident les champs de bits ont des adresses qui augmentent dans l'ordre dans lequel ils sont déclarés . Un pointeur vers un objet de structure, convenablement converti, pointe vers son membre initial (ou si ce membre est un champ binaire, puis vers l'unité dans laquelle il réside), et vice versa. Il peut y avoir un remplissage sans nom dans un objet de structure, mais pas à son début.

—— ISO/CEI 9899: 201x 6.7.2.1

9
yuan