在c语言中处理endianness++

2024-04-19 23:02:35 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在把一个系统从python翻译成c++。我需要能够在c++中执行通常通过使用Python的struct.unpack(将二进制字符串解释为数值)来执行的操作。对于整数值,我可以使用stdint.h中的数据类型使其工作(某种程度上):

struct.unpack("i", str) ==> *(int32_t*) str; //str is a char* containing the data

这对于小端二进制字符串是正确的,但对于大端二进制字符串则失败。基本上,我需要一个等效于在中使用>标记解包结构公司名称:

^{pr2}$

请注意,如果有更好的办法,我会洗耳恭听。但是,我不能使用c++11,也不能使用Boost之外的任何第三方库。我还需要能够解释float和double,如struct.unpack(">f", str)和{},但我将在解决这个问题时再进行解释。在

注意我应该指出,在这种情况下,我的机器的endianness与此无关。我知道我在代码中收到的比特流总是big-endian,这就是为什么我需要一个解决方案来覆盖big-endian情况。BoBTFish在评论中指出的文章似乎提供了一个解决方案。在


Tags: 字符串系统二进制情况整数解决方案struct数值
3条回答

对于32位和16位值:

这正是网络数据的问题,这是大端问题。您可以使用ntohl将32位转换为主机顺序,在您的例子中是little endian。在

The ntohl() function converts the unsigned integer netlong from network byte order to host byte order.

int res = ntohl(*((int32_t) str)));

这还可以处理主机是big-endian并且不会做任何事情的情况。在

对于64位值

在linux/BSD上,您可以查看64 bit ntohl() in C++?,它指向htobe64

These functions convert the byte encoding of integer values from the byte order that the current CPU (the "host") uses, to and from little-endian and big-endian byte order.

对于windows,请尝试:How do I convert between big-endian and little-endian values in C++?

它指向_byteswap_uint64,以及一个16位和32位的解决方案和一个特定于gcc的内置bswap(32/64)调用。在

其他尺寸

大多数系统没有16/32/64位长的值。在这一点上,我可能会尝试将它存储在一个64位的值中,移动它,然后它们进行转换。我会写一些好的测试。我怀疑这是一个不寻常的情况,更多的细节会有所帮助。在

首先,你的演员阵容:

char *str = ...;
int32_t i = *(int32_t*)str;

由于严格的别名规则,导致未定义的行为(除非str是用int32_t x; char *str = (char*)&x;之类的东西初始化的)。实际上,cast可能导致未对齐的读取,在某些平台上会导致总线错误(崩溃),而在其他平台上则会导致性能下降。在

相反,你应该做一些类似的事情:

^{pr2}$

有许多函数用于在主机的本机字节顺序和与主机无关的顺序之间交换字节:ntoh*()hton*(),其中{}不是什么,l或{}。由于不同的主机可能有不同的字节顺序,所以如果您正在读取的数据在所有平台上使用一致的序列化形式,那么这可能就是您想要使用的。在

ntoh(i);

在将字节复制到整数之前,您还可以在str中手动移动字节。在

std::swap(str[0],str[3]);
std::swap(str[1],str[2]);
std::memcpy(&i,str,sizeof(i));

也可以使用移位和按位运算符手动操作整数的值。在

std::memcpy(&i,str,sizeof(i));
i = (i&0xFFFF0000)>>16 | (i&0x0000FFFF)<<16;
i = (i&0xFF00FF00)>>8  | (i&0x00FF00FF)<<8;

一次一个字节地解压字符串。在

unsigned char *str;
unsigned int result;

result =  *str++ << 24;
result |= *str++ << 16;
result |= *str++ << 8;
result |= *str++;

相关问题 更多 >