如何正确将signed char[2]转换为uint16_t?CURL WebSocket回调关闭码计算异常求助
如何正确将signed char[2]转换为uint16_t?CURL WebSocket回调关闭码计算异常求助
哥们我太懂你这种踩有符号char坑的痛苦了!之前我在处理WebSocket关闭帧的时候也栽过一模一样的跟头,咱们先把问题根儿找出来,再给你搞定解决办法。
首先得搞明白你为啥得到奇怪的值:符号扩展在搞鬼!
你用的char是有符号类型(signed char),当你把负数(比如你例子里的data[1] = -24)参与移位运算时,C会自动把它提升为int类型。而负数的int是用补码表示的,高位全是1——比如-24作为signed char是0xE8,提升成int后就变成了0xFFFFFFE8。这时候你左移8位,得到的是0xFFFFE800,再和data[0](也就是0x03)按位或,结果就成了0xFFFFE803,这显然不是你想要的16位无符号关闭码。
那怎么解决?核心思路就是先把有符号char转成无符号的8位类型,再进行移位和拼接,彻底避免符号扩展的问题。给你两种靠谱的写法:
写法一:逐个强制转换为uint8_t
if (meta->flags & CURLWS_CLOSE) { // 先把每个signed char转成无符号的uint8_t,再拼接 uint16_t reason = ( (uint8_t)data[1] << 8 ) | (uint8_t)data[0]; // 这里就可以正常使用reason了 ... }
写法二:直接把指针转成unsigned char*
这种写法更清爽,适合处理更长的二进制数据:
if (meta->flags & CURLWS_CLOSE) { const unsigned char* udata = (const unsigned char*)data; uint16_t reason = (udata[1] << 8) | udata[0]; ... }
咱们拿你的例子验证一下:
data[1] = -24转成unsigned char后是0xE8(十进制232),左移8位得到0xE800data[0] = 3转成unsigned char是0x03- 按位或之后得到
0xE803,这就是正确的16位无符号关闭码了
另外提醒你一句:以后处理二进制数据(比如WebSocket帧、网络包)的时候,尽量都用unsigned char来操作,有符号类型的符号扩展真的是隐形坑,稍不注意就踩进去。
内容来源于stack exchange
相关产品推荐
相关产品推荐

