嗨,静态转换对位字段有效吗?因为在这里我创建了一个32位Long数据的位字段,因此我试图将其转换为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)
但是在这里,我收到一个错误,无法将scr_t强制转换为u32。任何人都可以提出一些建议
最佳答案
在C ++中,联合的任何一个字段在任何时候都处于活动状态。重新解释内存布局的唯一可移植方法是使用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));
注意:我已经添加了这一行
static_assert(sizeof(se_as_u32) <= sizeof(se), "UB detector");
为了保护
se
在其“边界”之外被读取:std::memcpy(&se_as_u32, &se, sizeof(se_as_u32));
这将从
sizeof(u32)
读取se
(可能是4)字节。如果se
小于4个字节长,则memcpy
将读取为“它的外部”,这是一种缓冲区溢出并导致未定义的行为(这很糟糕)。在不尊重不平等现象(
sizeof(se_as_u32) > sizeof(se)
)的情况下,将调用仁慈的abort()
,程序将立即崩溃,而不是花一些时间破坏一天的生产。关于c++ - static_cast可以用于位字段吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47711930/