Bit Fields in Structures

The Microsoft C compiler implements bit fields. However, many C compilers do not.

Bit fields allow you to access the individual bits within a data item. While the practice of accessing the bits in a data item is inherently nonportable, you can improve your chances of porting a program that uses bit fields if you make no assumptions about order of assignment, or size and alignment of bit fields.

Order of Assignment

The order of assignment of bit fields in memory is left to the implementation, so you cannot rely on a particular entry in a bit field structure to be in a higher order position than another. (This problem is similar to the portability constraint imposed by alignment of basic data types in structures. The C language does not define any specific layout for the storage of data items relative to one another.) See “Storage Order and Alignment” for more information.

Size and Alignment of Bit Fields

The Microsoft C compiler supports bit fields up to the size of the type long. Each individual member of the bit field structure can be up to the size of the declared type. Some compilers do not support bit field-structure elements that are longer than type int.

The following example defines a bit field, short_bitfield, that is shorter than type int:

struct short_bitfield

{

unsigned usr_bkup : 1; /* 0 <= usr_bkup < 1 */

unsigned usr_sec : 4; /* 9 <= usr_sec < 16 */

};

The following example defines a bit field, long_bitfield, that has an element longer than type int in a 16-bit environment:

struct long_bitfield

{

unsigned long disk_pos : 22; /* 0 <= disk_pos < 4,194,304 */

unsigned long rec_no : 10; /* 0 <= rec_no < 1,024 */

};

The bit field short_bitfield is likely to be supported by more implementations than long_bitfield.

Microsoft C Specific

The following example introduces another portability issue: alignment of data defined in bit fields.

struct long_bitfield

{

unsigned int day : 5; /* 0 <= day < 32 */

unsigned int month : 4; /* 0 <= month < 16 */

unsigned int year : 11; /* 0 <= year < 2048 */

};

In a 16-bit environment, Microsoft C does not allow an element in a structure to cross a word boundary. The first two elements, day and month, take up nine bits. The third, year, would cross a word boundary if it were to begin right after month, so instead it must begin on the next word boundary. There is thus a seven-bit gap between the month and year elements in Microsoft C's representation of this structure. However, other compilers may not use the same storage techniques.

Note that in a 32-bit environment, all three elements can fit within a single word, so there is no gap between any of the elements in Microsoft C's representation of the structure.