日常生活中常见的设备基本上都是小端系统,在同类设备(同为大端,或者同为小端)之间的通讯不需要考虑大小端问题,但是工业中有些生产商仍然会沿用大端系统,当在不同类设备之间通讯时,必须考虑多字节数据(short, int32,int64, float, double等)的字节序问题。不同的开发语言和不同的操作系统可能有自己的大小端转换接口,如果是c/c++程序开发,则可以借鉴下面的转换代码,对5种基本类型进行转换(虽然形参为有符号数,但是即便传递无符号数,也是可以正确转换的)。
注:如果是大端,则返回小端;如果是小端,则返回大端。
#pragma once
class LittleEndianConverter
{
public:
static __int16 Cpu_Short_To_BLe16(const __int16 v);
static __int32 Cpu_Int_To_BLe32(const __int32 v);
static float Cpu_Float_To_BLe32(const float v);
static __int64 Cpu_Int_To_BLe64(const __int64 v);
static double Cpu_Double_To_BLe64(const double v);
};
typedef union FLOAT_CONV
{
float f;
char c[4];
}FLOATCONV;
typedef union DOUBLE_CONV
{
double d;
char c[8];
}DOUBLECONV;
__int16 LittleEndianConverter::Cpu_Short_To_BLe16(const __int16 v)
{
//负数执行右移时左边会补1,即执行的是算数位移而非逻辑位移,因此要&0x00ff以消除高位的1
return ((v & 0xff) << 8) | (v >> 8 & 0x00ff);
}
__int32 LittleEndianConverter::Cpu_Int_To_BLe32(const __int32 v)
{
return ((v >> 24) & 0x000000ff)
| ((v & 0x00ff0000) >> 8 & 0x00ffffff)
| ((v & 0x0000ff00) << 8)
| (v << 24);
}
__int64 LittleEndianConverter::Cpu_Int_To_BLe64(const __int64 v)
{
return ((v >> 56) & 0x00000000000000ff)
| ((v & 0x00ff000000000000) >> 40 & 0x0000000000ffffff)
| ((v & 0x0000ff0000000000) >> 24 & 0x000000ffffffffff)
| ((v & 0x000000ff00000000) >> 8 & 0x00ffffffffffffff)
| ((v & 0x00000000ff000000) << 8)
| ((v & 0x0000000000ff0000) << 24)
| ((v & 0x000000000000ff00) << 40)
| (v << 56);
}
float LittleEndianConverter::Cpu_Float_To_BLe32(const float v)
{
/*
unsigned __int32 Tempval;
unsigned __int32 Retval;
float rv;
Tempval = *(unsigned __int32*)(&v);
Retval = Cpu_Int_To_BLe32(Tempval);
*((unsigned __int32*)(&rv))=Retval;
return rv;// works well
*/
FLOATCONV conv1, conv2;
conv1.f = v;
conv2.c[0] = conv1.c[3];
conv2.c[1] = conv1.c[2];
conv2.c[2] = conv1.c[1];
conv2.c[3] = conv1.c[0];
return conv2.f;
}
double LittleEndianConverter::Cpu_Double_To_BLe64(const double v)
{
/*
unsigned __int64 Tempval;
unsigned __int64 Retval;
double rv;
Tempval = *(unsigned __int64*)(&v);
Retval = Cpu_Int_To_BLe64(Tempval);
*((unsigned __int64*)(&rv))=Retval;
return rv;// works well
*/
DOUBLECONV conv1, conv2;
conv1.d = v;
conv2.c[0] = conv1.c[7];
conv2.c[1] = conv1.c[6];
conv2.c[2] = conv1.c[5];
conv2.c[3] = conv1.c[4];
conv2.c[4] = conv1.c[3];
conv2.c[5] = conv1.c[2];
conv2.c[6] = conv1.c[1];
conv2.c[7] = conv1.c[0];
return conv2.d;
}