1、字节序java
来自:http://ayazh.gjjblog.com/archives/1058846/swift
谈到字节序的问题,必然牵涉到两大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 Endianide
低地址 高地址
----------------------------------------->
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 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中提供了下面四个转换字节序的宏。ui
big endian:最高字节在地址最低位,最低字节在地址最高位,依次排列。
little endian:最低字节在最低位,最高字节在最高位,反序排列。.net
endian指的是当物理上的最小单元比逻辑上的最小单元小时,逻辑到物理的单元排布关系。我们接触到的物理单元最小都是byte,在通讯领域中,这里每每是bit,不过原理也是相似的。翻译
一个例子:
若是咱们将0x1234abcd写入到以0x0000开始的内存中,则结果为
big-endian little-endian
0x0000 0x12 0xcd
0x0001 0x34 0xab
0x0002 0xab 0x34
0x0003 0xcd 0x12
目前应该little endian是主流,由于在数据类型转换的时候(尤为是指针转换)不用考虑地址问题。指针
2、Big Endian 和 Little Endian名词的由来code
这两个术语来自于 Jonathan Swift 的《《格利佛游记》其中交战的两个派别没法就应该从哪一端--小端仍是大端--打开一个半熟的鸡蛋达成一致。:)
“endian”这个词出自《格列佛游记》。小人国的内战就源于吃鸡蛋时是究竟从大头(Big-Endian)敲开仍是从小头(Little-Endian)敲开,由此曾发生过六次叛乱,其中一个皇帝送了命,另外一个丢了王位。
咱们通常将endian翻译成“字节序”,将big endian和little endian称做“大尾”和“小尾”。
在那个时代,Swift是在讽刺英国和法国之间的持续冲突,Danny Cohen,一位网络协议的早期开创者,第一次使用这两个术语来指代字节顺序,后来这个术语被普遍接纳了
3、Big Endian 和 Little Endian优劣
来自:Dr. William T. Verts, April 19, 1996
Big Endian
判别一个数的正负很容易,只要取offset0处的一个字节就能确认。
Little Endian
长度为1,2,4字节的数,排列方式都是同样的,数据类型转换很是方便。
4、一些常见文件的字节序
来自:Dr. William T. Verts, April 19, 1996
Common file formats and their endian order are as follows:
5、比特序
来自:http://ayazh.gjjblog.com/archives/1058846/
我在8月9号的《Big Endian和Little Endian》一文中谈了字节序的问题。但是有朋友仍然会问,CPU存储一个字节的数据时其字节内的8个比特之间的顺序是否也有big endian和little endian之分?或者说是否有比特序的不一样?
实际上,这个比特序是一样存在的。下面以数字0xB4(10110100)用图加以说明。
Big Endian
msb lsb
---------------------------------------------->
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 1 | 0 | 1 | 1 | 0 | 1 | 0 | 0 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Little Endian
lsb msb ----------------------------------------------> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 0 | 0 | 1 | 0 | 1 | 1 | 0 | 1 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 实际上,因为CPU存储数据操做的最小单位是一个字节,其内部的比特序是什么样对咱们的程序来讲是一个黑盒子。也就是说,你给我一个指向0xB4这个数的指针,对于big endian方式的CPU来讲,它是从左往右依次读取这个数的8个比特;而对于little endian方式的CPU来讲,则正好相反,是从右往左依次读取这个数的8个比特。而咱们的程序经过这个指针访问后获得的数就是0xB4,字节内部的比特序对于程序来讲是不可见的,其实这点对于单机上的字节序来讲也是同样的。 那可能有人又会问,若是是网络传输呢?会不会出问题?是否是也要经过什么函数转换一下比特序?嗯,这个问题提得很好。假设little endian方式的CPU要传给big endian方式CPU一个字节的话,其自己在传输以前会在本地就读出这个8比特的数,而后再按照网络字节序的顺序来传输这8个比特,这样的话到了接收端不会出现任何问题。而假如要传输一个32比特的数的话,因为这个数在littel endian方存储时占了4个字节,而网络传输是以字节为单位进行的,little endian方的CPU读出第一个字节后发送,实际上这个字节是原数的LSB,到了接收方反倒成了MSB从而发生混乱。