2013-05-30 127 views
4

我有向我发送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,从index启动服务器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

这两台机器是排序? –

+0

我认为这与网络中的字节排序有关。网络字节顺序是big endian,大多数intel处理器都是little endian =>这是错误发生的地方。你看过C函数'htons()'和'ntohs()'吗? – jcxz

+0

但我也发送其他数据,我正准备提取正确的,我更倾向于我的逻辑,因为我正在从socket_buf正确解码它。我不确定是否需要按照设备上的操作进行操作。 – Rohit

回答

-3

您是否清除了socket_buf?

您是否确定您的计算机是大端点?

此外,我给你一个建议:使用或运营商,而不是加号。

这可以为您节省更多的时间。

mypkt.dateTime = (long) ((socket_buf[0] << 24) | (socket_buf[1] << 16) | socket_buf[2] << 8) | (socket_buf[3] << 0)); 
+1

原始文章中的代码是独立于endian的。按位OR等同于加法。启用优化器应该没有性能差异(但在这种情况下OR可能更易于阅读和理解)。另外,如果'socket_buf'是错误的整数类型,你建议的方法不起作用。长期签署的演员是毫无意义和不合理的。 – Lundin

+0

是的套​​接字缓冲区是清除的。 Lundin所以你的意思是说,我不需要这样做,因为它是从设备的原始代码中提取的 – Rohit

+0

这段代码似乎对我很好:mypkt.dateTime =((socket_buf [HB_PKT_DATE_TIME] << 0)+(socket_buf [HB_PKT_DATE_TIME +1] << 8)+(socket_buf [HB_PKT_DATE_TIME + 2] << 16)+(socket_buf [HB_PKT_DATE_TIME + 3] << 24)); – Rohit

8

的写代码是小尾数 - 它是先发送至少显著字节。

您的阅读代码预计为big endian - 它取第零个字节并将它向左移动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时代日期时间值,无论您用哪种字节序列来表示它。其他地方可能存在其他问题。

0

由于socket_buf被声明为unsigned char,因此socket_buf[0] << 24是一个错误。

socket_buf[0]是无符号字符,并将整数提升为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有什么关系,您的代码只是使用buffersock_buf之间的不一致顺序。

+0

一个'unsigned char'肯定会被提升为'_unsigned_ int'?无论如何,这不会导致崩溃。 – Alnitak

+0

好了,澄清 - 既然'0 - 0xff'都适合在int中,它确实会被提升为'int'而不是'uint',但_这不会引起符号扩展_。生成的'int'仍然具有范围'0 - 0xff'。 – Alnitak

+1

@Alnitak它将被提升为一个int,_not_为unsigned int(C11 6.3.1.1)。如果int是32位的,你基本上会得到这样的代码:'int32_t my_int = 0xFF; my_int << 24;'这是未定义的行为,按照C11 6.5.7。 – Lundin

相关问题