1. 什么是大端小端?
以16bit 的一个数字 0x0102 为例,尾部的02为低序字节,01为高序字节。大端小端的定义如下:低序字节处在起始地址的为小端(Little Endian),也称为低尾端;低序字节处在高地址的为大端(Big Endian)也称为高尾端。不同的CPU采用的端处理方式可能不同,如果一个数据以小端进行存储,但是在另一个处理机是大端,将会出现数据解析错误。比如在大端CPU中处理小端模式下存储的数字 0x0102 将被解析成 0x0201。因此有必要进行大小端的区分,并在必要时对数据进行转换。
2. 大端小端如何判断?
union little_big_endian
{
int b;
struct
{
bool is_lttle;
bool other[3];
}u;
};
bool is_little_endian()
{
little_big_endian lbe;
lbe.b = 1;
if( lbe.u.is_lttle )
{
return true;
}
else
{
return false;
}
}
如上所示,little_big_endian 是一个 union 类型,int 类型的 b 和 struct 类型的 u 共享同一块内存空间。在 is_little_endian 函数中,将 b 置位1,此时1位于低序字节。union 类型中的 is_little 位于内存的起始地址。按照大小端的定义,如果此时 is_liitle 为1则表示,低序字节位于起始地址,即为小端类型,否则为大端类型。
3. 大端小端的相互转换?
所谓大小端的不同即是同一个数据中的不同字节排列的顺序是相反的。如果想在一个大端的处理器上处理小端存储的数据(或者相反),则需要将同一个数据中的不同字节进行反转处理。如下程序展示了一个32位数据的转换方法。
void convert_endian_32(void *data)
{
//交换第0个字节和第3个字节
data[0]=data[0]^data[3]
data[3]=data[0]^data[3]
data[0]=data[0]^data[3]
//交换第1个字节和第2个字节
data[1]=data[1]^data[2]
data[2]=data[1]^data[2]
data[1]=data[1]^data[2]
}
上述程序利用异或操作来完成两个字节之间的交换,从而不必开辟新的交换空间。异或的特点是相同为0,不同为1。因此在经过 data[0] = data[0]^data[3] 之后,data[3] = data[0]^data[3] = data[0]^data[3]^data[3]=data[0],后者data[3] = data[0]^data[3] = data[0]^data[3]^data[0]=data[3]。从而完成了交换。