我正在尝试实现一个四字节值(首先是最重要的数据)来计算数据的总长度。我找到了一个代码片段来计算这个,但我没有得到输出中的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';
我的代码中是否遗漏了某些内容?
答案 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;
}