大小端

目录

  1. 1. 1. 定义
  2. 2. 2. 常见的CPU架构的字节序
  3. 3. 3. 判断方法
  4. 4. 4. 转换方法
  5. 5. 5. 为什么主机的字节序不统一

1. 定义

  • Little-Endian:低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。(逻辑上的低低高高)
  • Big-Endian:高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。(像数据流一样填充)
  • 网络字节序:TCP/IP各层协议将字节序定义为Big-Endian,因此TCP/IP协议中使用的字节序通常称之为网络字节序。

2. 常见的CPU架构的字节序

  • Big Endian : PowerPC、IBM、Sun
  • Little Endian : x86、DEC
  • ARM : 大小端可选

3. 判断方法

大小端问题主要涉及的是非单字节非字符串外的其余数据的表示和传递,如short型、int型等。判断主机大小端的方法有很多,常见的是联合体判断法。

bool isBigEndian() {
    union {
        int a;
        char b;
    } num;
    num.a = 0x1234;
    return (num.b == 0x12)
}

4. 转换方法

出于效率考虑,大小端的处理在客户端。在客户端socket过来时把服务器主机的大小端通知给客户端,这样服务器就不需要改动,直接传递数据就行,这时候可以在客户端代码中封装几个宏,在客户端在收到数据后,根据那些宏来判断是否转换以及得出转换后的数值。
大小端转换最有效也是最常见的方法就是移位法。

#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))

5. 为什么主机的字节序不统一

这是因为 各个CPU厂商出于不同的逻辑考量,换句话说 大端和小端有其各自的优势。
我们知道计算机正常的内存增长方式是从低到高(当然栈不是),取数据方式是从基址根据偏移找到他们的位置,从他们的存储方式可以看出,大端存储因为第一个字节就是高位,从而很容易知道它是正数还是负数,对于一些数值判断会很迅速。
而小端存储 第一个字节是它的低位,符号位在最后一个字节,这样在做数值四则运算时从低位每次取出相应字节运算,最后直到高位,并且最终把符号位刷新,这样的运算方式会更高效,也更符合我们手算的方式。