J'ai défini cette structure:
typedef struct
{
char A:3;
char B:3;
char C:3;
char D:3;
char E:3;
} col;
Le sizeof(col)
donnez-moi la sortie de 3, mais ne devrait-il pas être 2? Si je commente un seul élément, le sizeof
est 2. Je ne comprends pas pourquoi: cinq éléments de 3 bits sont égaux à 15 bits, et c'est moins de 2 octets.
Y a-t-il une «taille interne» dans la définition d'une structure comme celle-ci? J'ai juste besoin d'une clarification, car d'après ma notion du langage jusqu'à présent, je m'attendais à une taille de 2 octets, pas de 3.
signed char
ouunsigned char
, vous ne pouvez pas dire sans regarder la documentation si le compilateur traitera 'plain'char
dans un champ de bits comme signé ou non signé, et la décision pourrait (en théorie) être différente de la décision de savoir si 'plain'char
est signé ou non signé lorsqu'il est utilisé en dehors d'un champ de bits._Bool
,signed int
,unsigned int
ou un autre type défini par l' implémentation. L'utilisationchar
tombe donc dans la catégorie «autre type défini par l'implémentation».Réponses:
Étant donné que vous utilisez
char
comme type sous-jacent pour vos champs, le compilateur essaie de regrouper les bits par octets, et comme il ne peut pas mettre plus de huit bits dans chaque octet, il ne peut stocker que deux champs par octet.La somme totale de bits utilisée par votre structure est de 15, donc la taille idéale pour contenir autant de données serait a
short
.Le code ci-dessus (pour une plate-forme 64 bits comme la mienne) donnera en effet
2
pour la deuxième structure. Pour tout ce qui est plus grand que ashort
, la structure ne remplira pas plus d'un élément du type utilisé, donc - pour cette même plate-forme - la structure se retrouvera avec une taille quatre pourint
, huit pourlong
, etc.la source
char
etshort
?char
être non signées…Parce que vous ne pouvez pas avoir un champ de bits qui s'étend sur la limite d'alignement minimum (qui est de 1 octet), ils seront probablement emballés comme
(les ordres de champ / remplissage à l'intérieur du même octet ne sont pas intentionnels, c'est juste pour vous donner une idée, puisque le compilateur pourrait les définir comme il préfère)
la source
Les deux premiers champs de bits correspondent à un seul
char
. Le troisième ne peut pas entrer dans celachar
et a besoin d'un nouveau. 3 + 3 + 3 = 9 qui ne rentre pas dans un caractère 8 bits.Ainsi, la première paire prend un
char
, la deuxième paire prend unchar
, et le dernier champ de bits en obtient un troisièmechar
.la source
La plupart des compilateurs vous permettent de contrôler le remplissage, par exemple en utilisant
#pragma
s . Voici un exemple avec GCC 4.8.1:Notez que le comportement par défaut du compilateur est là pour une raison et vous donnera probablement de meilleures performances.
la source
Même si la norme ANSI C spécifie trop peu sur la façon dont les champs de bits sont emballés pour offrir un avantage significatif par rapport aux "compilateurs sont autorisés à emballer les champs de bits comme bon leur semble", elle interdit néanmoins dans de nombreux cas aux compilateurs de conditionner les choses de la manière la plus efficace.
En particulier, si une structure contient des champs de bits, un compilateur doit la stocker sous la forme d'une structure qui contient un ou plusieurs champs anonymes d'un certain type de stockage «normal», puis subdiviser logiquement chacun de ces champs en ses parties de champ de bits constituantes. Ainsi, étant donné:
Si
unsigned char
est 8 bits, le compilateur devrait allouer quatre champs de ce type, et attribuer deux champs de bits à tous sauf un (ce qui serait dans unchar
champ qui lui est propre). Si toutes leschar
déclarations avaient été remplacées parshort
, alors il y aurait deux champs de typeshort
, dont l'un contiendrait cinq champs de bits et l'autre contiendrait les deux autres.Sur un processeur sans restrictions d'alignement, les données pourraient être présentées plus efficacement en utilisant
unsigned short
pour les cinq premiers champs etunsigned char
pour les deux derniers, le stockage de sept champs de trois bits sur trois octets. Alors qu'il devrait être possible de stocker huit champs de trois bits sur trois octets, un compilateur ne pourrait permettre cela que s'il existait un type numérique de trois octets qui pourrait être utilisé comme type "champ externe".Personnellement, je considère que les champs de bits tels que définis sont fondamentalement inutiles. Si le code doit fonctionner avec des données binaires, il doit définir explicitement les emplacements de stockage des types réels, puis utiliser des macros ou d'autres moyens similaires pour accéder à leurs bits. Il serait utile que C prenne en charge une syntaxe telle que:
Une telle syntaxe, si elle était autorisée, permettrait au code d'utiliser des champs de bits de manière portable, sans tenir compte de la taille des mots ou de l'ordre des octets (foo0 serait dans les trois bits les moins significatifs de f1, mais ceux-ci pourraient être stockés au adresse inférieure ou supérieure). En l'absence d'une telle fonctionnalité, cependant, les macros sont probablement le seul moyen portable de fonctionner avec de telles choses.
la source