I need to create a structure with bitfields to encapsulate some data coming from hardware. Assuming I use compiler-specific mechanisms to enforce packing and ordering, is it possible to create a structure similar to the following (not syntactically correct):
typedef struct _BYTE_OF_DATA
{
uint8_t Reserved1 : 2;
struct
{
uint8_t BitWithSomeMeaning : 1;
uint8_t BitWithSomeOtherMeaning : 1;
} BitsWithMeaning;
uint8_t Reserved2 : 4;
} BYTE_OF_DATA, *PBYTE_OF_DATA;
static_assert(sizeof(BYTE_OF_DATA) == 1, "Incorrect size");
Which can then be accessed as follows:
BYTE_OF_DATA byteOfData;
byteOfData.Reserved1 = 1;
byteOfData.BitsWithMeaning.BitWithSomeOtherMeaning = 0;
The exact scheme I have described above will not work, because I guess the struct BitsWithMeaning
needs to start at a byte boundary. I was wondering if there is some other trick by which I can achieve this "nesting" of bitfields.
To elaborate on my previous comment something along these lines should allow the access style you desire. Albeit in a far from elegant way:
typedef union _BYTE_OF_DATA {
struct {
uint8_t Reserved1 : 2;
uint8_t : 2;
uint8_t Reserved2 : 4;
};
struct {
uint8_t : 2;
uint8_t BitWithSomeMeaning : 1;
uint8_t BitWithSomeOtherMeaning : 1;
uint8_t : 4;
} BitsWithMeaning;
} BYTE_OF_DATA, *PBYTE_OF_DATA;
Personally I would much prefer traditional field mask and position constants and mangle the registers manually. My experience is that accessing volatile I/O bitfields in this style invariably leads to inefficient and race-prone code.
You should use an union in this case
typedef union _BYTE_OF_DATA {
uint8_t data;
struct {
uint8_t padding1 : 2;
uint8_t BitWithSomeMeaning : 1;
uint8_t BitWithSomeOtherMeaning : 1;
uint8_t padding 2 : 4;
} BitsWithMeaning;
} BYTE_OF_DATA, *PBYTE_OF_DATA;
static_assert(sizeof(BYTE_OF_DATA) == 1, "Incorrect size");
So you can fill data in one shot :
BYTE_OF_DATA myByte;
myByte.data = someotherbyte;
And get bit with meaning :
int meaning1 = myByte.BitWithSomeMeaning;
int meaning2 = myByte.BitWithSomeOtherMeaning;
Or do the opposite :
myByte.data = 0; // Put all fields to 0
myByte.BitWithSomeMeaning = 1;
myByte.BitWithSomeOtherMeaning = 0;
int data = myByte.data;
In C++, the easiest solution might be
struct BYTE_OF_DATA
{
uint8_t bits;
private:
struct
{
bool getBitWithSomeMeaning() const { return bool(bits&0x20); }
bool getWithSomeOtherMeaning() const { return bool(bits&0x10); }
void setBitWithSomeMeaning(bool b);
void setWithSomeOtherMeaning(bool b);
} BitsWithMeaning;
};
No getters/setters for reserved fields obviously. Ctor probably should set those fields to 0 or 1, as the protocol specifies.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.