10.5.2 Bitfields in Structures
The MPLAB XC16 C Compiler fully supports bitfields in structures.
Bitfields are, by default, signed int
. They may be made
an unsigned int bitfield
by using a command line option (see the Options for Controlling the C Dialect section).
The first bit defined will be the LSb of the word in which it will be stored.
The compiler supports bitfields with any bit size, up to the size of the underlying type. Any integral type can be made into a bitfield. The allocation does not normally cross a bit boundary natural to the underlying type. For example:
struct foo {
long long i:40;
int j:16;
char k:8;
} x;
struct bar {
long long I:40;
char J:8;
int K:16;
} y;
struct foo
will have a size of 10 bytes using the
compiler. i
will be allocated at bit offset 0 (through 39). There will be
8 bits of padding before j
, allocated at bit offset 48. If
j
were allocated at the next available bit offset (40), it would cross
a storage boundary for a 16 bit integer. k
will be allocated after
j
, at bit offset 64. The structure will contain 8 bits of padding at
the end to maintain the required alignment in the case of an array. The alignment is 2
bytes because the largest alignment in the structure is 2 bytes.
struct bar
will have a size of 8 bytes using the
compiler. I
will be allocated at bit offset 0 (through 39). There is no
need to pad before J because it will not cross a storage boundary for a
char
. J
is allocated at bit offset 40.
K
can be allocated starting at bit offset 48, completing the structure
without wasting any space.
Unnamed bitfields may be declared to pad out unused space between active bits in control registers. For example:
struct foo {
unsigned int lo : 1;
unsigned int : 6;
unsigned int hi : 1;
} x;
A structure with bitfields may be initialized by supplying a comma-separated list of initial values for each field. For example:
struct foo {
unsigned int lo : 1;
unsigned int mid : 6;
unsigned int hi : 1;
} x = {1, 8, 0};
Structures with unnamed bitfields may be initialized. No initial value should be supplied for the unnamed members, for example:
struct foo {
unsigned int lo : 1;
unsigned int : 6;
unsigned int hi : 1;
} x = {1, 0};
will initialize the members lo
and hi
correctly.