最重要的字节计算

时间:2016-01-14 06:53:56

标签: c++ endianness

我正在尝试实现一个四字节值(首先是最重要的数据)来计算数据的总长度。我找到了一个代码片段来计算这个,但我没有得到输出中的4字节数据。相反,我只有一个2字节的值。

char bytesLen[4] ;
unsigned int blockSize = 535;
bytesLen[0] = (blockSize & 0xFF);
bytesLen[1] = (blockSize >> 8) & 0xFF;
bytesLen[2] = (blockSize >> 16) & 0xFF;
bytesLen[3] = (blockSize >> 24) & 0xFF;

std::cout << "bytesLen: " << bytesLen << '\n';

我的代码中是否遗漏了某些内容?

4 个答案:

答案 0 :(得分:2)

不,你没有。您将数组作为C字符串输出,null终止。第三个字节是nul,因此只显示两个字符。

这不是输出二进制值的合理方法。

此外,您首先要保存最不重要的字节,而不是最重要的字节。对于最重要的,您必须颠倒字节的顺序。

答案 1 :(得分:1)

这显示了如何在没有移位运算符和位掩码的情况下执行相同的操作。

#include <iostream>
#include <iomanip>
// C++11
#include <cstdint>

int main(void)
{
    // with union, the memory allocation is shared
    union {
        uint8_t bytes[4];
        uint32_t n;
    } length;

    // see htonl if needs to be in network byte order
    //  or ntohl if from network byte order to host
    length.n = 535;

    std::cout << std::hex;
    for(int i=0; i<4; i++) {
        std::cout << (unsigned int)length.bytes[i] << " ";
    }
    std::cout << std::endl;

    return 0;
}

答案 2 :(得分:0)

这是固定代码[未经测试]。请注意,这不会按原样编译。你需要稍微重新排序,但它应该有所帮助:

unsigned char bytesLen[4] ;
unsigned int blockSize = 535;

// little endian
#if 0
bytesLen[0] = (blockSize & 0xFF);
bytesLen[1] = (blockSize >> 8) & 0xFF;
bytesLen[2] = (blockSize >> 16) & 0xFF;
bytesLen[3] = (blockSize >> 24) & 0xFF;

// big endian
#else
bytesLen[3] = (blockSize & 0xFF);
bytesLen[2] = (blockSize >> 8) & 0xFF;
bytesLen[1] = (blockSize >> 16) & 0xFF;
bytesLen[0] = (blockSize >> 24) & 0xFF;
#endif

char tmp[9];

char *
pretty_print(char *dst,unsigned char *src)
{
    char *hex = "0123456789ABCDEF";
    char *bp = dst;
    int chr;

    for (int idx = 0;  idx <= 3;  ++idx) {
        chr = src[idx];
        *bp++ = hex[(chr >> 4) & 0x0F];
        *bp++ = hex[(chr >> 0) & 0x0F];
    }

    *bp = 0;

    return dst;
}

std::cout << "bytesLen: " << pretty_print(tmp,bytesLen) << '\n';

<强>更新

根据你的后续问题,为了连接二进制数据,我们可以使用类似字符串的函数,例如sprintf [因为二进制数据里面可能有0x00,这会阻止string transfer short]。此外,如果二进制数据中包含 no 0x00,则字符串函数将超出查找它的数组的末尾,并且会发生坏事。字符串函数也假设签名 char数据,在处理原始二进制文件时,我们要使用unsigned char

这是尝试的事情:

unsigned char finalData[1000];  // size is just example
unsigned char bytesLen[4];
unsigned char blockContent[300];

unsigned char *dst;

dst = finalData;

memcpy(dst,bytesLen,sizeof(bytesLen));
dst += sizeof(bytesLen);

memcpy(dst,blockContent,sizeof(blockContent));
dst += sizeof(blockContent);

// append more if needed in similar way ...

注意:上述假设blockContent具有固定大小。如果它具有可变数量的字节,我们需要将sizeof(blockContent)替换为(例如)bclen,其中blockContent

中的字节数

答案 3 :(得分:0)

如果你想要ms字节优先,那么你就颠倒了字节的顺序。

您输出的输出不正确,因为您将所有内容视为C字符串,即使它不是。摆脱char类型并修复打印。

在C ++中,它会是这样的:

#include <iostream>
#include <cstdint>

int main()
{
  uint8_t bytesLen[sizeof(uint32_t)];
  uint32_t blockSize = 535;

  bytesLen[3] = (blockSize >>  0) & 0xFF;
  bytesLen[2] = (blockSize >>  8) & 0xFF;
  bytesLen[1] = (blockSize >> 16) & 0xFF;
  bytesLen[0] = (blockSize >> 24) & 0xFF;

  bool removeZeroes = true;
  std::cout << "bytesLen: 0x";
  for(size_t i=0; i<sizeof(bytesLen); i++)
  {
    if(bytesLen[i] != 0)
    {
      removeZeroes = false;
    }

    if(!removeZeroes)
    {
      std::cout << std::hex << (int)bytesLen[i];
    }
  }
  std::cout << std::endl;

  return 0;
}