问题描述
我正在制作一个数据解析器/编码器,该数据解析器/编码器必须在两种字节序的不同机器上工作。
byte数组中的元数据动态声明用于表示每个整数的字节数,并且某些整数(我知道哪些整数)必须以big endian读取,而某些必须以little endian读取。
我目前编写了整数->字节函数(在macOS little endian上开发)并在Mac上运行。
void longlong_to_bytes_big(long long num,unsigned char *byte_arr,unsigned char num_bytes)
{
unsigned char i;
for(i=0; i<num_bytes; i++)
byte_arr[i] = (num >> ((num_bytes - i - 1) * 8)) & 0xFF;
}
void longlong_to_bytes_little(long long num,unsigned char num_bytes)
{
unsigned char i;
for(i=0; i<num_bytes; i++)
byte_arr[i] = (num >> (i * 8)) & 0xFF;
}
但是我担心这段代码实际上只适用于char,short和int在一台小型endian机器上,并且会给我相反的endianness在大型endian机器上。
然后从另一个方向看,我认为我无法将所有不同的整数大小组合为一个函数,但我认为每个函数都应如下所示:
long long bytes_to_longlong_big(unsigned char *byte_arr)
{
unsigned char i,a[8];
for(i=0; i<8; i++)
a[i] = byte_arr[8-i-1];
return *(long long *)a;
}
long long bytes_to_longlong_small(unsigned char *byte_arr)
{
return *(long long *)byte_arr;
}
但是我还是很确定,由于(long long *)的编译器实现,这些将在不同的endian机器上倒退。
是否存在机器字节序不可知的方式来完成此任务?只要有选择,我宁愿选择性能而不是简单性。
目标是这些字节数组的顺序相同,无论编译器的字节序如何,而且无论字节序如何,代码都需要正确解释字节数组。
解决方法
您可以按“网络顺序”保存/交换数据,然后在读写数据时使用诸如ntohl
和htonl
(以及朋友)之类的功能。这些功能将自动处理“当前”系统的耐久性。因此,您无需编写自己的代码。
您可能对诸如JSON,XML,YAML之类的文本格式感兴趣。对于人类开发人员而言,它们使调试更加容易。您会发现许多支持它们的库。
您可以找到一些与它们相关的C或C ++代码生成器(所以是metaprogramming方法)(rpcgen
,SWIG),并且可以考虑编写自己的C / C ++生成器使用诸如GPP或GNU m4或您的Guile或Python脚本之类的工具。
对于真正的网络交换(例如Ethernet)或磁盘IO,瓶颈通常是网络(或磁盘),而不是编码/解码处理。这就是为什么通常使用文本格式的原因。