我从硬件寄存器中得到一些值,这些值存储在 16 位无符号整数中,但这些值实际上是有符号的。知道最后一位是符号位,一位同事做了以下代码片段将它们转换为 2 的补码值:
/* Take 15 bits of the data (last bit is the sign) */
#define DATAMASK 0x7FFF
/* Sign is bit 15 (starting from zero) with the 15 bit data */
#define SIGNMASK 0x8000
#define SIGNBIT 15
int16_t calc2sComplement(uint16_t data)
{
int16_t temp, sign;
int16_t signData;
sign = (int16_t)((data & SIGNMASK) >> SIGNBIT);
if (sign)
{
temp = (~data) & DATAMASK;
signData = (short)(temp * -1);
}
else
{
temp = (data & DATAMASK);
signData = temp;
}
return(signData);
}
据我所知,无符号整数类型和有符号整数类型的区别仅在于它们的类型和最后一位的含义;所以像下面这样的铸造也应该起作用:
int16_t calc2sComplement(uint16_t data)
{
return(static_cast<int16_t>(data));
}
当需要将值推送到硬件时,与计算不同,反向操作很简单。前一种解决方案的优点是它没有工具链;因为它迟早会改变(gcc 4.4.7,所以 C++03),我宁愿不必这样做,但几年后编译时不会有任何回归。后者的优点是可读性更强,更接近标准,避免不必要的操作。
如果在工具链更改后再次编译(即使标准类型在工具链中的某处重新定义,而我并没有真正掌握它) ,在我的情况下,最好的方法是确保保持相同的行为?如果您保留第一个解决方案,如何改进它和/或编码反向转换(请记住,数据可以是数据缓冲区上的指针)?