基本上我正在读取二进制格式,其中4个字节指定要遵循的字符串的大小。所以我想将4个字符从缓冲区转换为1个整数。
这就是我所拥有的。
int FileReader::getObjectSizeForMarker(int cursor, int eof, char * buffer) {
//skip the marker and read next 4 byes
int cursor = cursor + 4; //skip marker and read 4
char tmpbuffer[4] = {buffer[cursor], buffer[cursor+1], buffer[cursor+2], buffer[cursor+3]};
int32_t objSize = tmpbuffer;
return objSize;
}
想法?
答案 0 :(得分:4)
手动拆包非常容易:
unsigned char *ptr = (unsigned char *)(buffer + cursor);
// unpack big-endian order
int32_t objSize = (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3];
答案 1 :(得分:3)
假设这些是MSB(即大端)。
unsigned char *p = (unsigned char*)buffer + cursor;
uint32_t uiSize = (unsigned int)*p <<24 |
(unsigned int)*(p+1) << 16 |
(unsigned int)*(p+2) << 8 |
(unsigned int)*(p+3);
在程序集之后将结果转换为signed int 。我知道,但我的打字技巧也是如此。
注意:老实说,我不记得隐式上传是否将符号从char扩展到int或者是否扩展,但如果是,那么这里的任何单个字节都是top-bit-点亮,如果* p不是,你可能会感到惊讶。因此看似偏执的无符号cast-o-festival,以及在完全组装后仅转换为signed-int的后续行为。
答案 2 :(得分:2)
这应该可以解决问题:
objSize = 0;
for (int i = 0; i < 4; ++ i)
objeSize += ((int)tmpbuffer[i]) << (8 * i);
OR
objSize = 0;
for (int i = 0; i < 4; ++ i)
objeSize += ((int)tmpbuffer[i]) << (8 * (3 - i));
nneonneo指出是大端的
答案 3 :(得分:0)
你所拥有的应该可以正常工作但是要替换这个
int32_t objSize = tmpbuffer;
这个
int32_t objSize = *((int32_t*)tmpbuffer);
答案 4 :(得分:0)
您可以使用ntohl
函数将网络转换为主机字节顺序。无需重新发明轮子。这也具有易于移植的优点,只要使用正确的头文件,它就可以在big-endian和little-endian操作系统上运行。下面是一个Windows示例,但该功能在Linux上也可用:
#include <winsock.h>
#include <iostream>
int main()
{
char buffer[] = "MARK\x00\x00\x00\x08";
// Point to the 4-byte network (big-endian) order value.
unsigned long * size = (unsigned long *)(buffer + 4);
// Dereference and convert it.
std::cout << ntohl(*size) << std::endl;
return 0;
}
输出:
8