最近在写代码的过程中发现一个自定义类型中一个非常隐晦的BUG,咱们直接看数据类型。
typedef union
{
uint16_t value;
struct{
uint8_t range :4; //读/写寄存器的数量
uint8_t register_addr :8; //读/写寄存器的地址
uint8_t Fixed_Pattern :4; //固定值 1000--读 0000--写
}Command;
}HAL6511_Cmd_Uni;
自定义一个联合体类型成员是一个无符号16bit的数值和16bit的结构体,结构体里面分成三个位段,三个位段一个组成16bit。
但是呢,当我创建了一个联合体,并给这个联合体赋值的时候,却出现了问题,赋值的后的结果与预想中的不一致。具体情况如下:
uint16_t hal6511_ReadRegister(uint8_t adr)
{
uint16_t spi_data;
HAL6511_Cmd_Uni CmdWord = {0};
CmdWord.Command.Fixed_Pattern = 8;
CmdWord.Command.register_addr = adr;
CmdWord.Command.range = 1;
#ifdef DEBUG_PRINTF
printf("\r\n命令字的值为:%#X", CmdWord.value);
#endif
}
使用上面的函数,传入地址0x80,按道理说CmdWord.Value的值应该是0x8801,但最后打印出来的值却是0x8001。
将原来传入的地址0x80修改为0x85之后,打印出来的调试信息为0x8501 现象很奇怪,后来将联合体类型声明中,将原来的 uint8_t 改为 uint16_t 之后问题解决。具体代码如下:
typedef union
{
uint16_t value;
struct{
uint16_t range :4; //读/写寄存器的数量
uint16_t register_addr :8; //读/写寄存器的地址
uint16_t Fixed_Pattern :4; //固定值1000 --读 0000--写
}Command;
}HAL6511_Cmd_Uni;
重新传入地址0x80,运行结果如下:
最后,虽然结果正常了,但是具体啥原理还是不太明白,推测可能是编译器(我用的keil)或者是联合体/结构体字节对齐的原因 ,不知道没有没大神能够帮忙解答一下,感谢!!!