Champs de bits en C avec struct contenant l’union de structs

Hm … pourquoi est-ce que, lorsque sizeof(struct MyStruct) , il en sizeof(struct MyStruct) 3 (au lieu de 2) pour ce code?

 #pragma pack(push, 1) struct MyStruct { unsigned char a : 6; union { struct { unsigned int b : 9; }; }; }; #pragma pack(pop) 

Au cas où cela serait important, j’exécuterais MinGW GCC 4.5.0 sur Windows 7 x64, mais honnêtement, le résultat est assez étrange pour moi. Je ne pense pas que le compilateur et le système d’exploitation importent trop ici. : \

Le champ ne peut pas commencer à une adresse non alignée octet. Vous vous attendez à:

 6 bits + 9 bits -> 15 bits -> 2 bytes 

mais ce que vous obtenez c’est:

 6 bits -> 1 byte 9 bits -> 2 bytes total -> 3 bytes 

Les données sont stockées en tant que:

 | 1 byte | 2 byte |3 byte | aaaaaaXX bbbbbbbb bXXXXX 

quand vous attendiez:

 | 1 byte | 2 byte | aaaaaabb bbbbbbbX 

edit: Pour clarifier basé sur les commentaires ci-dessous:

L’union (et la structure contenant) doit être alignée octet. Peu importe que le contenu ne soit que de 9 bits, l’union / struct elle-même fait 16 bits. Notez que vous ne pouvez pas effectuer les opérations suivantes:

 struct MyStruct { unsigned char a : 6; union { struct { unsigned int b : 9; } c:9; } d:9; }; 

Comme C ne vous laissera pas spécifier la taille de bit de la structure entière.

Ajoutant à la réponse donnée par @nss – toutes mes excuses, cela aurait été un commentaire si les commentaires n’étaient pas aussi limités en termes de formatage:

 #include  struct Test { unsigned short x : 6; unsigned short y : 1; unsigned short z; }; int main( int argc, char *argv[] ) { printf( "sizeof( Test ) = %d\n", sizeof( struct Test ) ); return 0; } 

Il imprime ‘4’ pour la taille. J’ai testé avec gcc, g ++ et les CC et cc de Sun Studio.

Ce n’est pas que je recommande de faire ce que vous essayez de faire, mais vous pourriez probablement faire ce que vous essayez de faire avec un syndicat. J’ai vu (mais pas moi-même écrit) un code qui ressemblait à ceci:

 struct Test { unsigned short x1 : 6; unsigned short x2 : 3; : 1; // unused unsigned short x3 : 4; // ... }; 

La syntaxe est peut-être un peu fausse ici … mais je ne le pense pas.

Le point étant: créez deux structures distinctes (ou une structure et une union) avec la mise en page souhaitée, puis insérez quelques membres factices où ils doivent se chevaucher et unissez-les ensemble.