自定义类型联合体与结构体位段混合是非常隐晦的错误

文章讲述了作者在编程时遇到的关于联合体类型赋值问题,发现当使用uint8_t而非uint16_t时,字节对齐影响了值的存储,调整类型后问题解决,但原理不明。作者寻求解释可能的原因,包括编译器和字节对齐规则。
摘要由CSDN通过智能技术生成

最近在写代码的过程中发现一个自定义类型中一个非常隐晦的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)或者是联合体/结构体字节对齐的原因 ,不知道没有没大神能够帮忙解答一下,感谢!!!

  • 14
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值