The Compiler provides six predefined macros to distinguish between the different allocations:
__BITFIELD_MSBIT_FIRST__ /* defined if bitfield allocation starts with MSBit */ __BITFIELD_LSBIT_FIRST__ /* defined if bitfield allocation starts with LSBit */ __BITFIELD_MSBYTE_FIRST__ /* allocation of bytes starts with MSByte */ __BITFIELD_LSBYTE_FIRST__ /* allocation of bytes starts with LSByte */ __BITFIELD_MSWORD_FIRST__ /* defined if bitfield allocation starts with MSWord */ __BITFIELD_LSWORD_FIRST__ /* defined if bitfield allocation starts with LSWord */
Using the above-listed defines, you can write compatible code over different Compiler vendors even if the bitfield allocation differs. Note that the allocation order of bitfields is important (refer to the following listing).
struct { /* Memory layout of I/O port: MSB LSB name: BITA | CCR | DIR | DATA | DDR2 size: 1 1 1 4 1 */ #ifdef __BITFIELD_MSBIT_FIRST__ unsigned int BITA:1; unsigned int CCR :1; unsigned int DIR :1; unsigned int DATA:4; unsigned int DDR2:1; #elif defined(__BITFIELD_LSBIT_FIRST__) unsigned int DDR2:1; unsigned int DATA:4; unsigned int DIR :1; unsigned int CCR :1; unsigned int BITA:1; #else #error "undefined bitfield allocation strategy!" #endif } MyIOport;
If the basic allocation unit for bitfields in the Compiler is a byte, the allocation of memory for bitfields is always from the most significant BYTE to the least significant BYTE. For example, __BITFIELD_MSBYTE_FIRST__ is defined as shown in the following listing:
/* example for __BITFIELD_MSBYTE_FIRST__ */ struct { unsigned char a:8; unsigned char b:3; unsigned char c:5; } MyIOport2; /* LSBIT_FIRST */ /* MSBIT_FIRST */ /* MSByte LSByte */ /* MSByte LSByte */ /* aaaaaaaa cccccbbb */ /* aaaaaaaa bbbccccc */