繁体   English   中英

如何以小端格式简单地从缓冲区重构数字

[英]How to simply reconstruct numbers from a buffer in little endian format

假设我有:

typedef unsigned long long uint64;

unsigned char data[BUF_SIZE];    

uint64 MyPacket::GetCRC()
{
  return (uint64)(data[45] | data[46] << 8 | 
         data[47] << 16 | data[48] << 24 |
         (uint64)data[49] << 32| (uint64)data[50] << 40 |
         (uint64)data[51] << 48| (uint64)data[52] << 56);
}

只是想知道是否有更清洁的方法。 我尝试对uint64变量使用memcpy,但这给了我错误的值。 我想我需要反过来。 数据为小端格式。

使用移位或序列的最大优点是,不管主机是大端还是小端,它都可以工作。

当然,您总是会调整表达式。 我个人尝试连接“ pairs”,一次是两个字节,然后是两个short,最后是两个long,因为这将帮助编译器生成更好的代码。

好吧,也许更好的主意是交换订单+演员表?

typedef unsigned long long uint64;

unsigned char data[BUF_SIZE];    

uint64 MyPacket::GetCRC()
{
  uint64 retval;
  unsigned char *rdata = reinterpret_cast<unsigned char*>(&retval);
  for(unsigned i = 0; i < 8; ++i) rdata[i] = data[52-i];
  return retval;
}

这是我自己的一个,与@ x13n提供的类似。

uint64 MyPacket::GetCRC()
{
    int offset=45;
    uint64 crc;
    memcpy(&crc, data+offset, 8);
    //std::reverse((char*)&crc, (char*)&crc + 8); // if this was a big endian machine
    return crc;
}

说实话,您所拥有的没有多大错。 它会工作,而且很快。 我要做的是将其格式化为更好的可读性:

uint64 MyPacket::GetCRC()
{
  return (uint64) data[45]       | 
         (uint64) data[46] << 8  | 
         (uint64) data[47] << 16 | 
         (uint64) data[48] << 24 |
         (uint64) data[49] << 32 | 
         (uint64) data[50] << 40 |
         (uint64) data[51] << 48 | 
         (uint64) data[52] << 56;
}

我猜您的另一个选择是改为循环执行:

uint64 MyPacket::GetCRC()
{
   const int crcoffset = 45;
   uint64 crc = 0;

   for (int i = 0; i < 8; i++)
   {
       crc |= (uint64)data[i + crcoffset] << (i * 8);
   }
   return crc;
}

这可能会导致非常相似的汇编(因为编译器可能会针对如此小的循环进行循环展开),但在我看来,这有点难以理解,因此您可以更好地利用已有的东西。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM