将unsigned存储在unsigned int的低16位中

rme*_*dor 5 c embedded integer-promotion

我在嵌入式系统上编写C语言.处理器架构是32位(sizeof(int)32位,sizeof(short)16位).有一个32位变量,它是一个内存映射控制寄存器(CTRL_REG),它被指定为只使用了底部的16位,它们包含一个带符号的16位整数值(写入更高的位没有任何影响).内存访问必须是32位对齐,所以我不能只是将指针碰到几个字节,而且我不能假设一个字节序.我担心通过将符号位扩展到第31位而不是将它留在我想要的第15位,自动类型提升会使我正在存储的内容混乱.在这个位置存放东西的最佳方法是什么?

这是我的原始代码,我几乎肯定是错的:

#define CTRL_REG   *((volatile unsigned int *)0x4000D008u)
short calibrationValue;

CTRL_REG = -2 * calibrationValue;
Run Code Online (Sandbox Code Playgroud)

然后我尝试了这个,但我认为它仍然可能在作业点受到整数提升:

CTRL_REG = (short)(-2 * calibrationValue);
Run Code Online (Sandbox Code Playgroud)

最后我想到了这个:

CTRL_REG = (unsigned short)(short)(-2 * calibrationValue);
Run Code Online (Sandbox Code Playgroud)

我无法很好地评估这些选项,因为它们都在我的测试中工作,因为它们calibrationValue是负的(它是每个设备特定的校准参数,因此在某些设备上可能是正的),所以在乘以-2后,我结束存储一个正值,因此我实际上没有遇到我在测试中期待的问题.

非常感谢您的帮助,即使只是说"您的想法太多".

ASh*_*lly 4

想想 -16(例如)在 16 位中的样子:“0xFFF0”,在 33 位中:“0xFFFFFFF0”。符号扩展正是您想要确保符号位位于正确位置的方法。由于上面的 16 位是无关的,所以用 1 填充就可以了。因此,创建一个有符号的 32 位值,然后将其转换为无符号的 32 位值以放入寄存器中:

  Int32 calreg= -2L * calibrationValue;
   CTRl_REG = (Uint32)calreg;
Run Code Online (Sandbox Code Playgroud)

如果您想将 0 写入高位,请在转换之前使用 0xFFFF 进行掩码。