我有一个嵌入式设备,它以这种格式发送UTC日期(日期为4个字节):
buffer.push_back((BYTE)(time_utc & 0x000000FF));
buffer.push_back((BYTE)((time_utc & 0x0000FF00) >> 8));
buffer.push_back((BYTE)((time_utc & 0x00FF0000) >> 16));
buffer.push_back((BYTE)((time_utc & 0xFF000000) >> 24));
在服务器上,我收到字节并将它们存储在socket_buf
中,从索引0-3开始并使用以下逻辑对其进行解码
mypkt.dateTime = ( ( socket_buf[0] << 24) +
(socket_buf[1 ] << 16) + socket_buf[2] << 8) +
(socket_buf[3] << 0));
但我不确定是否正确解码它因为我得到的日期不正确。任何人都可以建议我解码它的正确方法吗?我使用Linux命令解码日期(16711840是我通过解码获得的数字):
#date -d @16711840
答案 0 :(得分:8)
编写代码是 little endian - 它首先发送最低有效字节。
您的阅读代码期待 big endian - 它采用第0个字节并将其向左移位24位。
请注意,在这两种情况下代码都不依赖于本地机器的字节序 - 所写的代码与此无关,只是它们彼此不一致。
试试这个,而不是:
mypkt.dateTime = ((socket_buf[0] << 0) +
(socket_buf[1] << 8) +
(socket_buf[2] << 16) +
((uint32_t)socket_buf[3] << 24));
强制转换是必要的(但仅限于最后一班),因为0x80 - 0xff
将被转换为 signed int
,并且未定义转移到其中的位会发生什么签名位(感谢@Lundin)
注意:16711840不是“当前”Unix纪元日期时间值,无论您使用哪个字节顺序代表它。你可能在其他地方遇到其他问题。
答案 1 :(得分:0)
由于socket_buf
被声明为unsigned char,socket_buf[0] << 24
是一个错误。
socket_buf[0]
是unsigned char,将整数提升为int
。在这个特定系统上是16位还是32位并不重要,因为程序无论如何都会崩溃。在这两种情况下,它最终都是一个有符号的变量。您将左移一个带符号的变量并将二进制变换为符号位。然后你就此做了补充。
编写解码的正确方法是:
mypkt.dateTime = ( ((uint32_t)socket_buf[0] << 24) |
((uint32_t)socket_buf[1] << 16) |
((uint32_t)socket_buf[2] << 8) |
((uint32_t)socket_buf[3] << 0) );
此外,您似乎在编码和解码之间向后更改字节顺序。我不太清楚与endianess有什么关系,您的代码只是在buffer
与sock_buf
之间使用不一致的顺序。
答案 2 :(得分:-3)
你清除了socket_buf吗?
您确定您的计算机是大端的吗?
另外,我给你一个建议:使用或运算符而不是加号。
这可以为您节省更多时间。
mypkt.dateTime = (long) ( ( socket_buf[0] << 24) | (socket_buf[1] << 16) | socket_buf[2] << 8) | (socket_buf[3] << 0));