基础概念之大端模式和小端模式如何记忆

基础概念之大端模式和小端模式如何记忆



转自:http://blog.chinaunix.net/uid-25906157-id-3164447.html


端模式(Endian)的这个词出自Jonathan Swift书写的《格列佛游记》。这本书根据将鸡蛋敲开的方法不同将所有的人分为两类,从圆头开始将鸡蛋敲开的人被归为Big Endian,从尖头开始将鸡蛋敲开的人被归为Littile Endian。小人国的内战就源于吃鸡蛋时是究竟从大头(Big-Endian)敲开还是从小头(Little-Endian)敲开。在计算机业Big Endian和Little Endian也几乎引起一场战争。在计算机业界,Endian表示数据在存储器中的存放顺序。下文举例说明在计算机中大小端模式的区别。
大端模式
  所谓的大端模式,是指数据的高位,保存在内存的低地址中,而数据的低位,保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放;
  例子:
   低地址                                            高地址 
   &lw---------------------------------------->>
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     12    |      34    |     56      |     78    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  在大端模式下,应该这样读: 0x12345678
   记忆方法: 地址的增长顺序与值的增长顺序相反
小端模式
  所谓的小端模式,是指数据的高位保存在内存的高 地址中,而数 据的低位保存在内存的低地址中,这种存储模式将地址的高低和 数据位权有效地结合起来,高地址部分权值高,低地址部分权值低,和我们的逻辑方法一致。
  例子:
   低地址                                            高地址 
   &lw--------------------------------------->>
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     12     |      34    |     56      |     78    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

  在小端模式下,应该这样读: 0x78563412
   记忆方法: 地址的增长顺序与值的增长顺序相同
 

所有计算机处理器都必须在这两种Endian间作出选择。但某些处理器(如MIPS和IA-64)支持两种模式,可由编程者通过软件或硬件设置一种Endian。以下是一个处理器类型与对应的Endian的简表:

·  纯Big Endian: Sun SPARC, Motorola 68000Java Virtual Machine

·  Bi-Endian, 运行Big Endian模式: MIPS运行IRIX, PA-RISC,大多数PowerPowerPC系统

·  Bi-Endian, 运行Little Endian模式: MIPS  运行Ultrix,大多数DEC Alpha, IA-64运行Linux

·  Little Endian: Intel x86AMD64,DEC VAX

如何在程序中检测本系统的Endianess?可调用下面的函数来快速验证,如果返回值为1,则为Little Endian;为0则是Big Endian:

  1. int testendian() {
  2.     int x = 1;
  3.     return *((char *)&x);
  4. }

       Endianness对于网络通信也很重要。试想当Little Endian系统与Big Endian的系统通信时,如果不做适当处理,接收方与发送方对数据的解释将完全不一样。比如对以上C程序段中的变量d,Little Endian发送方发出11 22 33 44四个字节,Big Endian接收方将其转换为数值0x11223344。这与原始的数值大相径庭。

为了解决这个问题,TCP/IP协议规定了专门的"网络字节次序",即无论计算机系统支持何种Endian,在传输数据时,总是数值最高位的字节最先发送。从定义可以看出,网络字节次序其实是对应Big Endian的。

     为了避免因为Endianness造成的通信问题,及便于软件开发者编写易于平台移植的程序,特别定义了一些C语言预处理的宏来实现网络字节与主机字节次序之间的相互转换。htons()和htonl()用来将主机字节次序转成网络字节次序,前者应用于16位无符号数,后者应用于32位无符号数。ntohs()和ntohl()实现反方向的转换。这四个宏的原型定义可参考如下(Linux系统中可在netinet/in.h文件里找到):


  1. #if defined(BIG_ENDIAN) && !defined(LITTLE_ENDIAN)
  2. #define htons(A) (A)
  3. #define htonl(A) (A)
  4. #define ntohs(A) (A)
  5. #define ntohl(A) (A)
  6. #elif defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN)
  7. #define htons(A) ((((uint16)(A) & 0xff00) >> 8) | (((uint16)(A) & 0x00ff) << 8))
  8. #define htonl(A) ((((uint32)(A) & 0xff000000) >> 24) | (((uint32)(A) & 0x00ff0000) >> 8) | (((uint32)(A) & 0x0000ff00) << 8) | (((uint32)(A) & 0x000000ff) << 24))
  9. #define ntohs htons
  10. #define ntohl htohl
  11. #else
  12. #error "Either BIG_ENDIAN or LITTLE_ENDIAN must be #defined, but not both."
  13. #endif


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值