大端、小端字节顺序
1.人类习惯读写大端字节序,比如,十进制 12345,先读高位再到低位;计算机电路先处理低位字节,效率比较高,因为计算都是从低位开始的。所以,计算机的内部处理都是小端字节序。
2.计算机系统一般采用字节(Octet, 8 bit Byte)作为逻辑寻址单位。当物理单位的长度大于1个字节时,就要区分字节顺序(Byte Order, orEndianness)。常见的字节顺序有两种:Big Endian(High-byte first)和Little Endian(Low-byte first),常用的Intel X86(结构)平台,以及ARM,DSP采用小端模式,而PowerPC处理器则采用了大端模式
3.从系统的角度理解端模式
处理器在硬件上由于端模式问题在设计中有所不同。从系统的角度上看,端模式问题对软件和硬件的设计带来了不同的影响,当一个处理器系统中大小端模式同时存在时,必须要对这些不同端模式的访问进行特殊的处理。
PowerPC处理器主导网络市场,可以说绝大多数的通信设备都使用PowerPC处理器进行协议处理和其他控制信息的处理,这也可能也是在网络上的绝大多数协议都采用大端编址方式的原因。因此在有关网络协议的软件设计中,使用小端方式的处理器需要在软件中处理端模式的转变。而Pentium主导个人机市场,因此多数用于个人机的外设都采用小端模式,包括一些在网络设备中使用的PCI总线,Flash等设备,这也要求在硬件设计中注意端模式的转换。
4.常见的字节序
一般操作系统都是小端,而通讯协议是大端的。
1)常见CPU的字节序
Big Endian : PowerPC、IBM、Sun
Little Endian : x86、DEC
ARM既可以工作在大端模式,也可以工作在小端模式。
2)常见文件的字节序
Adobe PS – Big Endian
BMP – Little Endian
DXF(AutoCAD) – Variable
GIF – Little Endian
JPEG – Big Endian
MacPaint – Big Endian
RTF – Little Endian
另外,Java和所有的网络通讯协议都是使用Big-Endian的编码。
5.网络字节序 Network Order(即大端)
TCP/IP各层协议将字节序定义为Big-Endian,因此TCP/IP协议中使用的字节序通常称之为网络字节序;
主机序 Host Orader(即小端)
它遵循Little-Endian规则。所以当两台主机之间要通过TCP/IP协议进行通信的时候就需要调用相应的函数进行主机序(Little-Endian)和网络序(Big-Endian)的转换。
htonl() //32位无符号整型的主机字节顺序到网络字节顺序的转换(小端->>大端)
htons() //16位无符号短整型的主机字节顺序到网络字节顺序的转换 (小端->>大端)
ntohl() //32位无符号整型的网络字节顺序到主机字节顺序的转换 (大端->>小端)
ntohs() //16位无符号短整型的网络字节顺序到主机字节顺序的转换 (大端->>小端)
6.C++怎样判别大端小端
1.使用宏的方法:
const int endian =1;
#defineis_bigendian() ( (*(char*) &endian) == 0 )
#defineis_littlendbian() ( (*(char*) &endian) == 1 )
2.联合体:
boolIsLittleEndian()
{
union
{
longval;
charChar[sizeof(long)];
}u;
// 1-小端(Intel); 0-大端(Motor)
u.val =1;
if( u.Char[0] ==1)
{
// 小端
returntrue;
}
elseif( u.Char[sizeof(long)-1] ==1)
{
// 大端
returnfalse;
}
throw("Unknown!");
7.如何手算主机字节顺序转换为网络字节顺序?
假设某16位的整数,主机字节顺序的值是21,那么它的网络字节顺序是多少?
解决的步骤是:
1、将21化成二进制,二进制,如果不足16位就在其前面补0,补满16位。
21转换成二进制是:10101,在它前面补0,补满16位后就得到:
00000000#00010101
2、将这个16位二进制字符平分成两段,每段8位
0000000 000010101 == > 00000000#00010101
3、颠倒这两段的顺序,然后去掉第一个字符“1”前面的0,化成十进制就得到了网络字节顺序的值了。
00000000#00010101颠倒后:00010101#00000000
即00 01 01 01 00 000000
去掉第一个“1”前面的0得到:10 10 10 00 00 00 0
化成十进制得到:5376