我一直在寻找如何将big-endian转换为little-endians。但我找不到任何可以解决我问题的好处。似乎有很多方法可以进行这种转换。无论如何,以下代码在big-endian系统中正常工作。但是我应该如何编写转换函数,以便它也适用于little-endian系统?
这是一个功课,但它只是一个额外的,因为在学校运行大端系统的系统。只是我很好奇,并希望它能在我的家用电脑上运行
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ifstream file;
file.open("file.bin", ios::in | ios::binary);
if(!file)
cerr << "Not able to read" << endl;
else
{
cout << "Opened" << endl;
int i_var;
double d_var;
while(!file.eof())
{
file.read( reinterpret_cast<char*>(&i_var) , sizeof(int) );
file.read( reinterpret_cast<char*>(&d_var) , sizeof(double) );
cout << i_var << " " << d_var << endl;
}
}
return 0;
}
解决
所以Big-endian VS Little-endian只是字节的逆序。我写的这个功能似乎无论如何都符合我的目的。我在这里添加它以防万一其他人将来需要它。这只是双倍,但对于整数,要么使用建议的函数torak,要么可以通过使它只交换4个字节来修改此代码。
double swap(double d)
{
double a;
unsigned char *dst = (unsigned char *)&a;
unsigned char *src = (unsigned char *)&d;
dst[0] = src[7];
dst[1] = src[6];
dst[2] = src[5];
dst[3] = src[4];
dst[4] = src[3];
dst[5] = src[2];
dst[6] = src[1];
dst[7] = src[0];
return a;
}
答案 0 :(得分:20)
您可以使用模板进行endian交换,该模板将针对数据类型进行推广:
#include <algorithm>
template <class T>
void endswap(T *objp)
{
unsigned char *memp = reinterpret_cast<unsigned char*>(objp);
std::reverse(memp, memp + sizeof(T));
}
然后你的代码最终会看起来像:
file.read( reinterpret_cast<char*>(&i_var) , sizeof(int) );
endswap( &i_var );
file.read( reinterpret_cast<char*>(&d_var) , sizeof(double) );
endswap( &d_var );
cout << i_var << " " << d_var << endl;
答案 1 :(得分:4)
您可能对ntohl
系列函数感兴趣。它们旨在将数据从网络转换为主机字节顺序。网络字节顺序是大端,因此在大端系统上它们不做任何事情,而在小端系统上编译的相同代码将执行适当的字节交换。
答案 2 :(得分:4)
Linux提供endian.h
,它具有高达64位的高效字节交换例程。它还可以自动计算系统的字节顺序。 32位函数的定义如下:
uint32_t htobe32(uint32_t host_32bits); // host to big-endian encoding
uint32_t htole32(uint32_t host_32bits); // host to lil-endian encoding
uint32_t be32toh(uint32_t big_endian_32bits); // big-endian to host encoding
uint32_t le32toh(uint32_t little_endian_32bits); // lil-endian to host encoding
具有类似命名的16位和64位函数。 所以你要说
x = le32toh(x);
将little-endian编码的32位整数转换为主机CPU编码。这对于读取小端数据非常有用。
x = htole32(x);
将从主机编码转换为32位little-endian。这对于编写小端数据非常有用。
关于BSD系统的注意事项,等效的头文件是sys/endian.h
答案 3 :(得分:2)
假设你要继续,保留一个辅助函数的小库文件很方便。这些函数中的2个应该是4字节值的字节序交换,以及2字节值。对于一些可靠的示例(包括代码),请查看this article。
一旦你有了交换函数,每次读入错误的endian中的值时,都要调用相应的交换函数。有时这里的人们的绊脚石是单字节值不需要以字节交换,所以如果你正在读取类似于文件字符串的字符串,那应该是好的。只有在你读取一个值时,才需要交换多个字节(如整数值)。
答案 4 :(得分:2)
最好补充一点,MS在VS上也支持这个内联函数: