Reputation: 29
Hi does static cast work for bit fields?. Because here i have created a bit field of 32 bit Long data and i am trying to cast it to u32.
void CO2_SpiDriver::CreateBuffer() {
//#[ operation CreateBuffer()
typedef struct scr_t
{
union {
u32 data;
struct {
u8 CRC : 4;
u16 Datatosend : 16;
u8 DataLengthCode : 2;
u8 AddressReg : 4;
u8 ReadandWrite : 1;
u8 InstrucCode : 3;
u8 ExtChipId : 2;
};
};
} scr_t;
//set of data bits
scr_t se;
se.CRC = 0x00; //CRC BITS 0 to 3
se.Datatosend = 0x0000000000000000; //Data bits 19 to 4
se.DataLengthCode = 0x00; //DLC bits 21 and 20
se.AddressReg = 0x00; // SMP580 registers to access 25-22
se.ReadandWrite = 0x01; //Read|Write Reg 26
se.InstrucCode = 0x5; //InstrCode 29-27
se.ExtChipId = 0x2; //ExtChipId 31-30
static_cast<u32>(se)
But here i am getting an error that scr_t cannot be casted to u32. Can anyone give some suggestions
Upvotes: 0
Views: 1240
Reputation: 40080
In C++, only one of the fields of an union is active at any time. The only portable way to reinterpret a memory layout is to use std::memcpy
:
struct bf {
u8 CRC : 4;
u16 Datatosend : 16;
u8 DataLengthCode : 2;
u8 AddressReg : 4;
u8 ReadandWrite : 1;
u8 InstrucCode : 3;
u8 ExtChipId : 2;
};
bf se;
se.CRC = 0x00; //CRC BITS 0 to 3
se.Datatosend = 0x0000000000000000; //Data bits 19 to 4
se.DataLengthCode = 0x00; //DLC bits 21 and 20
se.AddressReg = 0x00; // SMP580 registers to access 25-22
se.ReadandWrite = 0x01; //Read|Write Reg 26
se.InstrucCode = 0x5; //InstrCode 29-27
se.ExtChipId = 0x2; //ExtChipId 31-30
u32 se_as_u32;
static_assert(sizeof(se_as_u32) <= sizeof(se), "UB detector"); // avoid reading buffer overflow (see explanation below)
std::memcpy(&se_as_u32, &se, sizeof(se_as_u32));
Note: I've added the line
static_assert(sizeof(se_as_u32) <= sizeof(se), "UB detector");
in order to protect se
to be read outside of its "bounds":
std::memcpy(&se_as_u32, &se, sizeof(se_as_u32));
This reads sizeof(u32)
(probably 4) bytes from se
. In the eventuality that se
was smaller than 4 bytes long, memcpy
would read "outside of it", this is a kind of buffer overflow and result in undefined behaviour (this is bad).
In the case where the inequality was not respected (sizeof(se_as_u32) > sizeof(se)
), a merciful abort()
would be called and the program would promptly crash instead of maybe working for a time and destroy the production one day.
Upvotes: 4