Nested Bit Fields in C / C ++

I need to create a structure with bit fields in order to encapsulate some data coming from the hardware. Assuming I use compiler-specific mechanisms to provide packaging 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"); 

They can be accessed as follows:

 BYTE_OF_DATA byteOfData; byteOfData.Reserved1 = 1; byteOfData.BitsWithMeaning.BitWithSomeOtherMeaning = 0; 

The exact scheme described above will not work, because I think that struct BitsWithMeaning should start from the byte boundary. I was wondering if there is any other trick with which I can achieve this β€œnesting” of bitfields.

+6
source share
3 answers

To think through my previous comment, something in this direction should allow you to get an access style. Although this is far from an 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 prefer the traditional field mask and constant positions and manually cast the registers. My experience is that access to volatile I / O bit fields in this style invariably leads to inefficient and subject to racial code.

+6
source

In this case you should use union

 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 in the data with one shot:

 BYTE_OF_DATA myByte; myByte.data = someotherbyte; 

And get a bit with the value:

 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; 
+1
source

In C ++, the simplest 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; }; 

It is clear that there are no cleaners / setters for reserved fields. Ctor should probably set these fields to 0 or 1, as the protocol indicates.

0
source

Source: https://habr.com/ru/post/984056/


All Articles