谈到字节序的问题,必然牵涉到两大CPU派系。那就是Motorola的PowerPC系列CPU和Intel的x86系列CPU。PowerPC系列采用big endian方式存储数据,而x86系列则采用little endian方式存储数据。那么究竟什么是big endian,什么又是little endian呢?

其实big endian是指低地址存放最高有效字节(MSB),而little endian则是低地址存放最低有效字节(LSB)。

用文字说明可能比较抽象,下面用图像加以说明。比如数字0x12345678在两种不同字节序CPU中的存储顺序如下所示:

Big Endian

低地址                                            高地址
   ----------------------------------------->
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     12     |      34    |     56      |     78    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Little Endian

低地址                                            高地址
   ----------------------------------------->
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     78     |      56    |     34      |     12    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

从上面两图可以看出,采用big endian方式存储数据是符合我们人类的思维习惯的(也就是看上去比较顺眼)。而little endian在计算机里用起来比较高效。

为什么要注意字节序的问题呢?你可能这么问。当然,如果你写的程序只在单机环境下面运行,并且不和别人的程序打交道,那么你完全可以忽略字节序的存在。但是,如果你的程序要跟别人的程序产生交互呢?在这里我想说说两种语言。C/C++语言编写的程序里数据存储顺序是跟编译平台所在的CPU相关的,而JAVA编写的程序则唯一采用big endian方式来存储数据。试想,如果你用C/C++语言在x86平台下编写的程序跟别人的JAVA程序互通时会产生什么结果?就拿上面的0x12345678来说,你的程序传递给别人的一个数据,将指向0x12345678的指针传给了JAVA程序,由于JAVA采取big endian方式存储数据,很自然的它会将你的数据翻译为0x78563412。什么?竟然变成另外一个数字了?是的,就是这种后果。因此,在你的C程序传给JAVA程序之前有必要进行字节序的转换工作。

无独有偶,所有网络协议也都是采用big endian的方式来传输数据的。所以有时我们也会把big endian方式称之为网络字节序。当两台采用不同字节序的主机通信时,在发送数据之前都必须经过字节序的转换成为网络字节序后再进行传输。ANSI C中提供了下面四个转换字节序的宏。

big endian:最高字节在地址最低位,最低字节在地址最高位,依次排列。 
little endian:最低字节在最低位,最高字节在最高位,反序排列。

endian指的是当物理上的最小单元比逻辑上的最小单元小时,逻辑到物理的单元排布关系。咱们接触到的物理单元最小都是byte,在通信领域中,这里往往是bit,不过原理也是类似的。

一个例子:
如果我们将0x1234abcd写入到以0x0000开始的内存中,则结果为
                big-endian     little-endian
0x0000     0x12              0xcd
0x0001     0x34              0xab
0x0002     0xab              0x34
0x0003     0xcd              0x12

目前应该little endian是主流,因为在数据类型转换的时候(尤其是指针转换)不用考虑地址问题。

嵌入式系统开发者应该对Little-endian和Big-endian模式非常了解。采用Little-endian模式的CPU对操作数的存放方式是从低字节到高字节,而Big-endian模式对操作数的存放方式是从高字节到低字节。也就是说Big-endian模式符合人的习惯,而Little-endian更加方便计算机操作。

例如,16bit宽的数0x1234在Little-endian模式CPU内存中的存放方式(假设从地址0x4000开始存放)为:
内存地址 0x4000 0x4001 
存放内容 0x34 0x12

而在Big-endian模式CPU内存中的存放方式则为:
内存地址 0x4000 0x4001 
存放内容 0x12 0x34

32bit宽的数0x12345678在Little-endian模式CPU内存中的存放方式(假设从地址0x4000开始存放)为:
内存地址 0x4000 0x4001 0x4002 0x4003 
存放内容 0x78 0x56 0x34 0x12

而在Big-endian模式CPU内存中的存放方式则为:
内存地址 0x4000 0x4001 0x4002 0x4003 
存放内容 0x12 0x34 0x56 0x78

若判断处理器是Big还是Little模式,有两种方法。

1、

int i=1;   
    char *p=(char *)&i;   
    if(*p==1)     
           printf("1");  
    else
           printf("2");

大小端存储问题,如果小端方式(i占至少两个字节的长度)则i所分配的内存最小地址那个字节中就存着1,其他字节是0.大端的话则1在i的最高地址字节处存放,char是一个字节,所以强制将char型量p指向i则p指向的一定是i的最低地址,那么就可以判断p中的值是不是1来确定是不是小端.

字节序

字节序,又称端序尾序英语Endianness)。在计算机科学领域中,字节序是指存放多字节数据的字节(byte)的顺序,典型的情况是整数在内存中的存放方式和网络传输的传输顺序。Endianness有时候也可以用指位序(bit)。

一般而言,字节序指示了一个UCS-2字符的哪个字节存储在低地址。如果LSByteMSByte的前面,即LSB为低地址,则该字节序是小端序;反之则是大端序。在网络编程中,字节序是一个必须被考虑的因素,因为不同的处理器体系可能采用不同的字节序。在多平台的代码编程中,字节序可能会导致难以察觉的bug

基本的字节序

对于单一的字节(a byte),大部分处理器以相同的顺序处理位元(bit),因此单字节的存放方法和传输方式一般相同。

对于多字节数据,如整数(32位机中一般占4字节),在不同的处理器的存放方式主要有两种,以内存中0x0A0B0C0D的存放方式为例,分别有以下几种方式:

0x前缀代表十六进制。

大端序 

大端序(英:big-endian)或称大尾序

  • 数据以8bit为单位:

地址增长方向  →

...

0x0A

0x0B

0x0C

0x0D

...

示例中,最高有效位(MSB, Most Significant Byte)是0x0A 存储在最低的内存地址处。下一个字节0x0B存在后面的地址处。正类似于十六进制字节从左到右的阅读顺序。

  • 数据以16bit为单位:

地址增长方向  →

...

0x0A0B

0x0C0D

...

   

最高的16bit单元0x0A0B存储在低位。

小端序 

小端序(英:little-endian)或称小尾序

  • 数据以8bit为单位:

地址增长方向  →

...

0x0D

0x0C

0x0B

0x0A

...

最低有效位(LSB,Least Significant Byte)是0x0D 存储在最低的内存地址处。后面字节依次存在后面的地址处。

  • 数据以16bit为单位:

地址增长方向  →

...

0x0DOC

0x0BOA

...

   

最低的16bit单元0xOD0C存储在低位。

  • 更改地址的增长方向:

当更改地址的增长方向,使之由右至左时,表格更具有可阅读性。

←  地址增长方向

...

0x0A

0x0B

0x0C

0x0D

...

最低有效位(LSB)是0x0D 存储在最低的内存地址处。后面字节依次存在后面的地址处。

←  地址增长方向

...

0x0A0B

0x0C0D

...

   

最低的16bit单元0x0C0D存储在低位。

混合序 

混合序(英:middle-endian)具有更复杂的顺序。以PDP-11为例,0x0A0B0C0D被存储为:

  • 32bitPDP-11的存储方式

地址增长方向  →

...

0x0B

0x0A

0x0D

0x0C

...

可以看作最高的16bit位和低位以大端序存储,但16bit内部以小端存储。

处理器体系

x86MOS Technology 6502Z80VAXPDP-11等处理器为Little endian。

网络序

网络传输一般采用大端序,也被称之为网络字节序,或网络序IP协议中定义大端序为网络字节序。

伯克利socket API定义了一组转换函数,用于16和32bit整数在网络序和本机字节序之间的转换。htonl,htons用于本机序转换到网络序;ntohl,ntohs用于网络序转换到本机序。

位序

一般用于描述串行设备的传输顺序。网络协议中只有数据链路层的底端会涉及到。

小端序(先传低位)的串行协议

大端序(先传高位)的串行协议 

Little-endian和Big-endian的更多相关文章

  1. c#,关于Big Endian 和 Little Endian,以及转换类

    Big Endian:最高字节在地址最低位,最低字节在地址最高位,依次排列. Little Endian:最低字节在最低位,最高字节在最高位,反序排列. 当在本地主机上,无需注意机器用的是Big En ...

  2. 字符编码笔记:ASCII,Unicode和UTF-8,附带 Little endian和Big endian的解释

    作者: 阮一峰 日期: 2007年10月28日 今天中午,我突然想搞清楚Unicode和UTF-8之间的关系,于是就开始在网上查资料. 结果,这个问题比我想象的复杂,从午饭后一直看到晚上9点,才算初步 ...

  3. Endian.BIG_ENDIAN和Endian.LITTLE_ENDIAN(http://smartblack.iteye.com/blog/1129097)

    Endian.BIG_ENDIAN和Endian.LITTLE_ENDIAN 在ByteArray和Socket中,能看到一个属性endain. endian : String 更改或读取数据的字节顺 ...

  4. 大endian和little endian

    大endian和little endian      一般Intel处理器或X86平台是小端 ,只是有点老了摩托罗拉的处理器将采用大端,掌握一下小端序.     小端序一般指低地址存低字节.高地址存高 ...

  5. Big Endian与Litter Endian

    Big Endian是大端,Litter Endian是小端,意思很明了,但是很难记住谁是谁.每次涉及到这个概念的时候,我都会GOOGLE一下,浪费精力. 怎样才能永远记住他们呢?网上搜索了一下,有很 ...

  6. 数据在内存中的存储方式( Big Endian和Little Endian的区别 )(x86系列则采用little endian方式存储数据)

    https://www.cnblogs.com/renyuan/archive/2013/05/26/3099766.html 1.故事的起源 “endian”这个词出自<格列佛游记>.小 ...

  7. 关于Big Endian 和 Little Endian

    Big Endian 和 Little Endian 一.字节序 来自:http://ayazh.gjjblog.com/archives/1058846/ 谈到字节序的问题,必然牵涉到两大CPU派系 ...

  8. java代码中存在的Big Endian 和 Little Endian

    Big Endian 和 Little Endian 详解 Java中的Big(Little)-endian问题的一种解决方法 主机序和网络序  很重要很重要 几种ip存放形式 Big-Endian和 ...

  9. 大端和小端(Big endian and Little endian)

    一.大端和小端的问题 对于整型.长整型等数据类型,Big endian 认为第一个字节是最高位字节(按照从低地址到高地址的顺序存放数据的高位字节到低位字节):而 Little endian 则相反,它 ...

  10. 大端和小端(big endian little endian)

    一.大端和小端的问题 对于整型.长整型等数据类型,Big endian 认为第一个字节是最高位字节(按照从低地址到高地址的顺序存放数据的高位字节到低位字节):而 Little endian 则相反,它 ...

随机推荐

  1. MyBatis关联查询,一对多关联查询

    实体关系图,一个国家对应多个城市 一对多关联查询可用三种方式实现: 单步查询,利用collection标签为级联属性赋值: 分步查询: 利用association标签进行分步查询: 利用collect ...

  2. eclipse 安装报错

    14 11:17:13] ERROR: org.eclipse.equinox.p2.transport.ecf code=1002 Unable to read repository at http ...

  3. 上传文件到aws的s3存储

    只要有aws-cli客户端就可以上传文件到aws的S3存储.可以在任意机器上.这里以centos为例. 1.安装python.pip. # yum install -y python python-p ...

  4. Django入门项目实践(上)

    项目结构 1.建立项目 File -->> New Project... 第一个Location是项目所在的目录,第二个Location是项目独立的Python运行环境,我们称之为Virt ...

  5. 一、spring boot 1.5.4入门(web+freemarker)

    1.配置maven文件pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmln ...

  6. Java 8 中 Date与LocalDateTime、LocalDate、LocalTime互转

    Java 8中 java.util.Date 类新增了两个方法,分别是from(Instant instant)和toInstant()方法 // Obtains an instance of Dat ...

  7. Python之旅:并发编程之协程

    一 引子 本节的主题是基于单线程来实现并发,即只用一个主线程(很明显可利用的cpu只有一个)情况下实现并发,为此我们需要先回顾下并发的本质:切换+保存状态 cpu正在运行一个任务,会在两种情况下切走去 ...

  8. Python之文件与目录操作(os、zipfile、tarfile、shutil)

    Python中可以用于对文件和目录进行操作的内置模块包括: 模块/函数名称 功能描述 open()函数 文件读取或写入 os.path模块 文件路径操作 os模块 文件和目录简单操作 zipfile模 ...

  9. String的用法------程序猿的双十一

    小感慨:我就静静的写着代码玩,度过一年一度的双十一,今晚就更新进度,整理笔记. package com.mon11.day10; import static org.junit.Assert.*; i ...

  10. NodeJS 笔记 URL模块

    url模块 ,包含分析和解析 URL 的工具. var url = require('url'); url.parse(urlStr[, parseQueryString][, slashesDeno ...