从uint8_t到uint16_t的转换

3

如何将uint8_t转换为uint16_t?

目前我是通过以下方式将uint16_t分解为uint8_t:

    packetBuffer.header[0] = ((co2Val>>8) & 0xff);
    packetBuffer.header[1] = (co2Val & 0xff);
    packetBuffer.header[2] = ((humVal>>8)&0xff);
    packetBuffer.header[3] = (humVal & 0xff);
    packetBuffer.header[4] = ((tempVal>>8)&0xff);
    packetBuffer.header[5] = (tempVal & 0xff);

co2Val、humVal 和 tempVal 都是 uint16_t 类型。

然而,为了得到对应的值,我需要将它们改回来。在另一端会以 uint8_t buf[16] 的形式接收这些值。

我是这样做的:

    CO2Val = (buf[0]<<8)|buf[1];
    HumVal = (buf[2]<<8)|buf[3];
    HumVal = (HumVal & 0x0fff);
    TempVal = (buf[4]<<8)|buf[5];
    TempVal = (TempVal & 0x3fff);

结果不同。有人知道为什么吗?谢谢。

你能展示一些你得到的错误结果的例子吗?你还应该选择标记此问题为C或C++,而不是两者都选择,因为答案可能不同。 - R.. GitHub STOP HELPING ICE
结果有什么区别?此外,为什么要屏蔽HumValTempVal的某些位? - Marcelo Cantos
2
顺便说一下,你代码中的 & 0xff 操作都是多余的冗杂代码。任何赋值/转换为无符号类型的操作都会自动包含一个隐式的 & TYPE_MAX 操作。 - R.. GitHub STOP HELPING ICE
2个回答

2
您如何将uint8_t转换为uint16_t?
只需简单地进行赋值即可:
uint8_t  val_u8  = ...
uint16_t val_u16 = val_u8;

我认为你想要问的问题是“如何将uint_8组合成uint_16?”

我猜你可能在这一行遇到了问题。

CO2Val = (buf[0]<<8)|buf[1];

如果 buf[0]uint8_t 类型。在进行位移操作之前,将其转换为 uint16_t 类型以确保有足够的空间容纳 8 个位(否则,这些位会“掉落”最高有效位的边缘)

uint16_t CO2Val = ( (uint16_t) buf[0] << 8) | buf[1];


1
这个答案对于C语言来说是不正确的。buf[0]<<8会将buf[0]提升为int类型,并作为int类型进行位移操作。 - R.. GitHub STOP HELPING ICE

1

我猜你其实是在使用C++,而不是C语言,buf [0] << 8等操作可能因移位大小至少达到类型宽度而产生未定义的行为。在C语言中,这种情况不会发生,因为算术操作数始终至少升级为int

无论如何,让我们尝试一些更简单、更易读的代码:

packetBuffer.header[0] = co2Val/256;
packetBuffer.header[1] = co2Val;
packetBuffer.header[2] = humVal/256;
packetBuffer.header[3] = humVal;
packetBuffer.header[4] = tempVal/256;
packetBuffer.header[5] = tempVal;

并且:

CO2Val = buf[0]*256+buf[1];
HumVal = buf[2]%16*256+buf[3];
TempVal = buf[4]%64*256+buf[5];

我保留了您对 HumValTempVal 上位字节截断的操作,但最好的实践是检查超出范围的值并发出某种错误提示。

编辑:由于 OP 澄清了语言是 C,我不确定有什么问题。似乎我们仍然缺少信息。也许查看涉及到的缓冲区的转储数据会很有用。


只是让您知道:您的示例代码在Vala中将两个uint8组合成一个uint16非常有效。从UDP包中获取了两个十六进制值作为uint8,应将其视为一个uint16。使用您的CO2Val示例完成了这项工作,并且它很好用。 - Steffen Winkler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接