Question:
Using Visual C++ 6.0, I recently attempted to create a structure to implement a data message that my application had to process. The following code segment produced unexpected results (names have been changed to protect the innocent):
struct X{ BOOL field1 : 4; BOOL field2 : 2; BOOL field3 : 1; BOOL field4 : 1; BOOL field5 : 4; BOOL field6 : 4;};struct Y{ BOOL field1 : 1; BOOL field2 : 1; ... BOOL field10 : 1; int Spare : 6;};struct message{ X messageField1; Y messageField2;};
The structures X and Y were each packed into 16 bits, as I had intended. But the message structure took 64 bits, not 32. I included 16 bits of padding before messageField1 and messageField2. Changing BOOL to unsigned char fixed the problem.
Can you explain this, please?
Answer:
Almost everything about bit-fields is compiler- and platform-dependent. In your example, BOOL appears to be the culprit. BOOL is synonymous with “signed int.” As such, it requires 32-bit alignment on Win32. This means that bit structures that contain less than 32 bits may get additional padding bytes to make them fit into a 32-bit word boundary.
When you define a bit field structure that occupies a total of 16 bits or less, always use char or short. Choosing a larger integral type can cause the insertion of extra padding bytes. Furthermore, using a signed type such as BOOL to define a one-bit field is a bad idea, and it likely will cause unexpected results because a signed field always reserves one bit for the sign. If you need a signed bit field, use at least two bits. Otherwise, use an unsigned type explicitly:
struct BITS{ unsigned char f1: 1; // possible values: 0,1 signed char f2: 2 // possible values: -1,0,1};