谈到字节序的问题,必然牵涉到两大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. oracle-表空间剩余空间大小占比查询

    select tablespace_name, max_gb, used_gb, round(100 * used_gb / max_gb) pct_used from (select a.table ...

  2. C# 妈妈再打我一下生成器

    设计背景 网上很火的一个"妈妈再打我一下"的漫画图片,给了网友无限的想象发挥空间,此小程序可以给图片添加配文的形式,快速生成图片 设计思路 GDI+ 绘图技术,在图片基础上添加文字 ...

  3. LOJ2542 PKUWC2018随机游走(概率期望+容斥原理)

    如果直接dp,状态里肯定要带上已走过的点的集合,感觉上不太好做. 考虑一种对期望的minmax容斥:其中Max(S)为遍历完S集合的期望步数,Min(S)为遍历到S集合中一个点的期望步数.当然才不管怎 ...

  4. SECD machine

    SECD machine 对程序语言理论的理解 程序语言理论主要研究语法.语义及语言的实现.编程语言有语法,各种数学逻辑.结构化数据都有语法.乔姆斯基的语言体系及巴科斯范式是语法分析的基础,语法分析将 ...

  5. 学习Spring Boot:(十八)Spring Boot 中session共享

    前言 前面我们将 Redis 集成到工程中来了,现在需要用它来做点实事了.这次为了解决分布式系统中的 session 共享的问题,将 session 托管到 Redis. 正文 引入依赖 除了上篇文章 ...

  6. 【BZOJ1047】[HAOI2007]理想的正方形(单调队列,动态规划)

    [BZOJ1047][HAOI2007]理想的正方形(单调队列,动态规划) 题面 BZOJ 洛谷 题解 直接一个单调队列维护一下没给点和它前面的\(n\)个位置的最大值,再用一次单调队列维护连续\(n ...

  7. CronExpression

    CronTrigger CronTriggers往往比SimpleTrigger更有用,如果您需要基于日历的概念,而非SimpleTrigger完全指定的时间间隔,复发的发射工作的时间表.CronTr ...

  8. Nagios服务器端配置文件详解

    Nagios服务器端安装部署详解见:http://www.cnblogs.com/ginvip/p/6505948.html Nagios 主要用于监控一台或者多台本地主机及远程的各种信息,包括本机资 ...

  9. Spark记录-官网学习配置篇(二)

    ### Spark SQL Running the SET -v command will show the entire list of the SQL configuration. #scala/ ...

  10. sql server查询某年某月有多少天

    sql语句如下: ),) date from (),,)+'-01' day) t1, ( ) t2 ),) ),,)+'%' 查询结果如下: 2017年2月共有28天,查询出28条记录.