4.3.5.2 Bit-fields In Structures

MPLAB XC8 C Compiler fully supports bit-fields in structures.

Bit-fields are always allocated within 8-bit words, even though it is usual to use an int type in the definition. The first bit defined will be the LSb of the word in which it will be stored. When a bit-field is declared, it is allocated within the current 8-bit unit if it will fit; otherwise, a new byte is allocated within the structure.

Bit-fields can span the boundary between 8-bit allocation units; however, the code to access bit-fields that do so is extremely inefficient. A plain bit-field is unsigned; however the -fsigned-bitfields option can be used to change that behavior.

Consider the following definition:

struct {
    unsigned        lo : 1;
    unsigned        dummy : 6;
    unsigned        hi : 1;
} foo;

This will produce a structure occupying 1 byte.

If foo was ultimately linked at address 0x10, the field lo will be bit 0 of address 0x10 and field hi will be bit 7 of address 0x10. The LSb of dummy will be bit 1 of address 0x10.

Note: Accessing bit-fields larger than a single bit can be very inefficient. If code size and execution speed are critical, consider using a char type or a char structure member, instead. Be aware that some SFRs are defined as bit-fields. Most are single bits, but some can be multi-bit objects.

Unnamed bit-fields can be declared to pad out unused space between active bits in control registers. For example, if dummy is never referenced, the structure above could have been declared as:

struct {
    unsigned        lo : 1;
    unsigned           : 6;
    unsigned        hi : 1;
} foo;

A structure with bit-fields can be initialized by supplying a comma-separated list of initial values for each field. For example:

struct {
    unsigned        lo  : 1;
    unsigned        mid : 6;
    unsigned        hi  : 1;
} foo = {1, 8, 0};

Structures with unnamed bit-fields can be initialized. No initial value should be supplied for the unnamed members, for example:

struct {
    unsigned        lo  : 1;
    unsigned            : 6;
    unsigned        hi  : 1;
} foo = {1, 0};

will initialize the members lo and hi correctly.

A bit-field that has a size of 0 is a special case. The Standard indicates that no further bit-field is to be packed into the allocation unit in which the previous bit-field, if any, was placed.