一、什么是大小端
内存地址 | 小端模式存放内容 | 大端模式存放内容 |
0x0000 | 0x78 | 0x12 |
0x0001 | 0x56 | 0x34 |
0x0002 | 0x34 | 0x56 |
0x0003 | 0x12 | 0x78 |
以0x12345678为例,可以看出。
大端,存放规则:12345678 显示规则:12345678
即低地址放高位,高地址放地位。
小端,存放规则:78563412 显示规则:12345678
即低地址放低位,高地址放高位。
二、哪些平台是大端、哪些平台是小端、为什么有大小端之分
2.1 常见的CPU架构的大小端举例(有待验证)
Big Endian : PowerPC 非NT、IBM、SUN SPARC、HP-PA UNIX、MIPS UNIX、RS/6000 UNIX、Motorola m68k
Little Endian : PowerPC NT、x86(Intel、AMD等)、DEC Alpha、HP-PA NT、MIPS NT、
其中ARM的大小端是可选的,网络tcp/ip 是大端。
2.2 为什么有大小端之分
在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为8bit。但是在C语言中除了8bit的char之外,还有16bit的short型,32bit的int型(要看具体的编译器),另外,对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如果将多个字节安排的问题。
因此就导致了大端存储模式和小端存储模式。
三、什么时候需要大小端转换、哪些数据需要判断大小端、如何判断大小端
3.1 什么时候需要大小端转换
大小端转换一般用在跨平台通信和资源共享上面,同一个平台上面的开发,它们的数据存放规则和显示规则是一致的,不需要考虑大小端相关问题。
仍然以0x12345678为例
小端到大端传输
如小端机器发送的int类型是0x12345678,那么数据的存放规则是 78 56 34 12
发送的时候从低地址开始读取,即发送出去是0x12345678,实际上是78 56 34 12
大端主机依次读取从低地址开始存放数据,低地址到高地址,大端机存放规则: 78563412
然后大端机的显示规则:0x78563412
这样看来,结果需要转换。
大端到小端传输
如大端机器发送:int类型的0x12345678,存放规则:12 34 56 78
发送的时候从低地址开始读取,即发送出去是0x12345678,实际上是:12 34 56 78
小端主机依次读取从低地址开始存放数据,低地址到高地址,小端机存放规则: 12345678
然后小端机的显示规则:0x78563412
这样看来,结果需要转换。
大端到大端传输
如大端机器发送:int类型的0x12345678,存放规则:12 34 56 78
发送的时候从低地址开始读取,即发送出去是0x12345678,实际上是:12 34 56 78
大端主机依次读取从低地址开始存放数据,低地址到高地址,大端机存放规则: 12345678
然后大端机的显示规则: 0x12345678
这样看来,结果不需要转换。
小端到小端传输
如小端机器发送:int类型的0x12345678,存放规则:78 56 34 12
发送的时候从低地址开始读取,即发送出去是0x12345678,实际上是:78 56 34 12
小端主机依次读取从低地址开始存放数据,低地址到高地址,小端机存放规则: 78563412
然后小端机的显示规则:0x12345678
这样看来,结果不需要转换。
3.2 哪些数据需要判断大小端
正如上面说的除了8bit的数据不需要进行数据转换,它只对应着一个地址单元,其余的short、int、long等类型都需要进行大小端判断。
3.3 如何进行大小端判断
最常见的就是联合体判断方法了,代码如下:
bool isBigEndian()
{
union
{
int a;
char b;
}num;
num.a = 0x12345678;
return ( num.b == 0x12 )
}
四、大小端如何转换,常用方法是什么
大小端转换最有效也是最常见的方法就是移位法,如下:
#define __SWP16(A) (( ((uint16)(A) & 0xff00) >> 8) | \
(( (uint16)(A) & 0x00ff) << 8))
#define __SWP32(A) ((( (uint32)(A) & 0xff000000) >> 24) | \
(( (uint32)(A) & 0x00ff0000) >> 8) | \
(( (uint32)(A) & 0x0000ff00) << 8) | \
(( (uint32)(A) & 0x000000ff) << 24))
最后,出于效率考虑,大小端应该在最开始的通信过程中就要约定好,尽量减少系统资源的消耗。