2009-04-06 01:12 AM
how to use the bit fields structure?
2011-05-17 04:08 AM - last edited on 2024-03-05 05:35 AM by Peter BENSCH
Posted on May 17, 2011 at 13:08
Hi guys;
My question is purely software.
I want to define a structure of bit fields of a variable to minimize the use of masks.
Example :
typedef struct _reg_struct
{
vu8 field1 : 1;
vu8 field2 : 1;
vu8 field3 : 2;
vu8 field4 : 3;
vu8 field5 : 1;
} REG_struct; /* 8 bits */
REG_struct REG;
vu8 var;
......
REG.field1 = 1;
REG.Field4 = 5;
REG.field2 = 1;
REG.Field3 = 3;
My question is, how to affect «var» with the entire structure fields of «REG»? the cast doesn't work :
var=(vu8)REG ;
Any suggestion (independant of compilers)?
[ This message was edited by: monmsn1234 on 05-04-2009 18:32 ]
2011-05-17 04:08 AM
It is incorrect to assume that the REG_struct occupies 8 bits. The compiler allocates the bits in chunks of an implementation defined size. Furthermore, it is implementation defined in what order the fields are allocated from the chunk. Thus you cannot store the struct in a vu8 and expect it to work. So seriously consider why you need bit fields in the first place, then why you need to store them in an integer.
Besides, the declaration of the fields with vu8 is incorrect, it should be either 'signed' or 'unsigned'.2011-05-17 04:08 AM
vu8 -> volatile unsigned char it's defined in ST library!!.
Any ideas for my problem?!2011-05-17 04:08 AM
Hm, I just tried specifying 'char' in the bit field declaration, and to my great surprise gcc made the struct exactly one byte. I wonder if that is a gcc feature, I can't remember reading about it in the standard. I may stand corrected. :)
2011-05-17 04:08 AM
I used this method before (PCW a compiler for Microchip microcontrollers) and it worked fine!!
I want to fill all the fields of the structure and send it via SPI (8 bits). How can I use the variable REG (with type REG_struct) in the SPI_I2S_SendData(SPI_TypeDef* SPIx, u16 Data) function ??2011-05-17 04:08 AM
Turns out I was correct...
6.7.2.1 of the C99 standard says 4 ''A bit-field shall have a type that is a qualified or unqualified version of _Bool, signed int, unsigned int, or some other implementation-defined type.'' 'char' in a bit-field declaration is not portable. 10 ''An implementation may allocate any addressable storage unit large enough to hold a bit-field. If enough space remains, a bit-field that immediately follows another bit-field in a structure shall be packed into adjacent bits of the same unit. If insufficient space remains, whether a bit-field that does not fit is put into the next unit or overlaps adjacent units is implementation-defined. The order of allocation of bit-fields within a unit (high-order to low-order or low-order to high-order) is implementation-defined. The alignment of the addressable storage unit is unspecified.'' There is no guarantee that your bit-field will fit in a byte. 13 ''Within a structure object, the non-bit-field members and the units in which bit-fields reside have addresses that increase in the order in which they are declared. A pointer to a structure object, suitably converted, points to its initial member (or if that member is a bit-field, then to the unit in which it resides), and vice versa. There may be unnamed padding within a structure object, but not at its beginning.'' If you still want to take this road, you are assured by the standard that a pointer to the structure will point to the first storage-unit of the bit-field. So you can portably convert it to a vu8 in the following way: val = *(vu8*)& REG; However, you have no idea if this byte will hold the bit-fields you declared.2011-05-17 04:08 AM
Quote:
On 05-04-2009 at 17:52, Anonymous wrote: Hi guys; My question is purely software. I want to define a structure of bit fields of a variable to minimize the use of masks. Example : typedef struct _reg_struct { vu8 field1: 1; vu8 field2: 1; vu8 field3: 2; vu8 field4: 3; vu8 field5: 1; } REG_struct; /* 8 bits */ REG_struct REG; vu8 var ; ...... REG.field1 = 1 ; REG.Field4 = 5 ; REG.field2 = 1 ; REG.Field3 = 3 ; ......... My question is, how to affect « var » with the entire structure fields of « REG »? the cast doesn’t work : var=(vu8)REG ; Any suggestion (independant of compilers)? [ This message was edited by: monmsn1234 on 05-04-2009 18:32 ] Hi, Try to use union. Jan2011-05-17 04:08 AM
The only guaranteed, compiler-independent method for doing this it to use masks and shifts.
For example (assuming Field 1 is the most significant bit):
var = (u8) 0
| ((Field1 & 0x01) << 7)
| ((Field2 & 0x01) << 6)
| ((Field3 & 0x03) << 4)
| ((Field4 & 0x07) << 1)
| ((Field5 & 0x01) << 0);
(The initial 0, and the final shift of 0, are for aesthetics only!).
A union will also work, but you'll need to verify that the bits are stored as expected for your compiler, and there's no guarantee that the same code will be implemented the same way on another compiler.
Steve.
2011-05-17 04:08 AM
Quote:
My question is purely software.
In fact, it is purely 'C'Quote:
I want to define a structure of bit fields of a variable to minimize the use of masks.
There is absolutely no guarantee whatsoever that the compiler will implement bitfields any more efficiently than doing masks ''manually'' As others have pointed out, there are so many doubts & uncertainties about the implementations of bitfields across different compilers that you are probably best to just stick with masks!