Linux-Big-Endian和Little-Endian转换
转自:http://blog.csdn.net/aklixiaoyao/article/details/7548860
在各种计算机体系结构中,对于字节、字等的存储机制有所不同,因而引发了计算机通信领域中一个很重要的问题,即通信双方交流的信息单元(比特、字节、字、双字等等)应该以什么样的顺序进行传送。如果不达成一致的规则,通信双方将无法进行正确的编/译码从而导致通信失败。目前在各种体系的计算机中通常采用的字节存储机制主要有两种:Big-Endian和Little-Endian,下面先从字节序说起。
一、什么是字节序
字节序,顾名思义字节的顺序,再多说两句就是大于一个字节类型的数据在内存中的存放顺序(一个字节的数据当然就无需谈顺序的问题了)。其实大部分人在实际的开发中都很少会直接和字节序打交道。唯有在跨平台以及网络程序中字节序才是一个应该被考虑的问题。
在所有的介绍字节序的文章中都会提到字节序分为两类:Big-Endian和Little-Endian,引用标准的Big-Endian和Little-Endian的定义如下:
a) Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。
b) Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。
c) 网络字节序:TCP/IP各层协议将字节序定义为Big-Endian,因此TCP/IP协议中使用的字节序通常称之为网络字节序。
1.1 什么是高/低地址端
首先我们要知道我们C程序映像中内存的空间布局情况:在《C专家编程》中或者《Unix环境高级编程》中有关于内存空间布局情况的说明,大致如下图:
----------------------- 最高内存地址 0xffffffff
栈底
栈
栈顶
-----------------------
NULL (空洞)
-----------------------
堆
-----------------------
未初始化的数据
----------------------- 统称数据段
初始化的数据
-----------------------
正文段(代码段)
----------------------- 最低内存地址 0x00000000
以上图为例如果我们在栈上分配一个unsigned char buf[4],那么这个数组变量在栈上是如何布局的呢?看下图:
栈底(高地址)
----------
buf[3]
buf[2]
buf[1]
buf[0]
----------
栈顶 (低地址)
1.2 什么是高/低字节
弄清了高/低地址,接着考虑高/低字节。有些文章中称低位字节为最低有效位,高位字节为最高有效位。如果我们有一个32位无符号整型0x12345678,那么高位是什么,低位又是什么呢?其实很简单。在十进制中我们都说靠左边的是高位,靠右边的是低位,在其他进制也是如此。就拿 0x12345678来说,从高位到低位的字节依次是0x12、0x34、0x56和0x78。
高/低地址端和高/低字节都弄清了。我们再来回顾一下Big-Endian和Little-Endian的定义,并用图示说明两种字节序:
以unsigned int value = 0x12345678为例,分别看看在两种字节序下其存储情况,我们可以用unsigned char buf[4]来表示value:
Big-Endian: 低地址存放高位,如下图:
栈底 (高地址)
---------------
buf[3] (0x78) -- 低位
buf[2] (0x56)
buf[1] (0x34)
buf[0] (0x12) -- 高位
---------------
栈顶 (低地址)
Little-Endian: 低地址存放低位,如下图:
栈底 (高地址)
---------------
buf[3] (0x12) -- 高位
buf[2] (0x34)
buf[1] (0x56)
buf[0] (0x78) -- 低位
--------------
栈顶 (低地址)
二、各种Endian
2.1 Big-Endian
计算机体系结构中一种描述多字节存储顺序的术语,在这种机制中最重要字节(MSB)存放在最低端的地址上。采用这种机制的处理器有IBM3700系列、PDP-10、Mortolora微处理器系列和绝大多数的RISC处理器。
+----------+
| 0x34 |<-- 0x00000021
+----------+
| 0x12 |<-- 0x00000020
+----------+
图 1:双字节数0x1234以Big-Endian的方式存在起始地址0x00000020中
在Big-Endian中,对于bit序列 中的序号编排方式如下(以双字节数0x8B8A为例):
bit 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+-----------------------------------------+
val | 1 0 0 0 1 0 1 1 | 1 0 0 0 1 0 1 0 |
+----------------------------------------+
图 2:Big-Endian的bit序列编码方式
2.2 Little-Endian
计算机体系结构中 一种描述多字节存储顺序的术语,在这种机制中最不重要字节(LSB)存放在最低端的地址上。采用这种机制的处理器有PDP-11、VAX、Intel系列微处理器和一些网络通信设备。该术语除了描述多字节存储顺序外还常常用来描述一个字节中各个比特的排放次序。
+----------+
| 0x12 |<-- 0x00000021
+----------+
| 0x34 |<-- 0x00000020
+----------+
图3:双字节数0x1234以Little-Endian的方式存在起始地址0x00000020中
在 Little-Endian中,对于bit序列中的序号编排和Big-Endian刚好相反,其方式如下(以双字节数0x8B8A为例):
bit 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+-----------------------------------------+
val | 1 0 0 0 1 0 1 1 | 1 0 0 0 1 0 1 0 |
+-----------------------------------------+
图 4:Little-Endian的bit序列编码方式
注2:通常我们说的主机序(Host Order)就是遵循Little-Endian规则。所以当两台主机之间要通过TCP/IP协议进行通信的时候就需要调用相应的函数进行主机序(Little-Endian)和网络序(Big-Endian)的转换。
注3:正因为这两种机制对于同一bit序列的序号编排方式恰恰相反,所以《现代英汉词典》中对MSB的翻译为“最高有效位”欠妥,故本文定义为“最重要的bit/byte”。
2.3 Middle-Endian
除了Big-Endian和Little-Endian之外的多字节存储顺序就是Middle- Endian,比如以4个字节为例:象以3-4-1-2或者2-1-4-3这样的顺序存储的就是Middle-Endian。这种存储顺序偶尔会在一些小型机体系中的十进制数的压缩格式中出现。
嵌入式系统开发者应该对Little-endian和Big-endian模式非常了解。采用 Little-endian模式的CPU对操作数的存放方式是从低字节到高字节,而Big-endian模式对操作数的存放方式是从高字节到低字节。
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-Endian和Little-Endian优缺点
Big-Endian优点:靠首先提取高位字节,你总是可以由看看在偏移位置为0的字节来确定这个数字是正数还是负数。你不必知道这个数值有多长,或者你也不必过一些字节来看这个数值是否含有符号位。这个数值是以它们被打印出来的顺序存放的,所以从二进制到十进制的函数特别有效。因而,对于不同要求的机器,在设计存取方式时就会不同。
Little-Endian优点:提取一个,两个,四个或者更长字节数据的汇编指令以与其他所有格式相同的方式进行:首先在偏移地址为0的地方提取最低位的字节,因为地址偏移和字节数是一对一的关系,多重精度的数学函数就相对地容易写了。
如果你增加数字的值,你可能在左边增加数字(高位非指数函数需要更多的数字)。因此,经常需要增加两位数字并移动存储器里所有Big-endian顺序的数字,把所有数向右移,这会增加计算机的工作量。不过,使用Little- Endian的存储器中不重要的字节可以存在它原来的位置,新的数可以存在它的右边的高位地址里。这就意味着计算机中的某些计算可以变得更加简单和快速。
四、如何检查处理器是Big-Endian还是Little-Endian?
由于联合体union的存放顺序是所有成员都从低地址开始存放,利用该特性就可以轻松地获得了CPU对内存采用Little- endian还是Big-endian模式读写。例如:
int checkCPUendian()
{
union
{
unsigned int a;
unsigned char b;
}c;
c.a = 1;
return (c.b == 1);
}
五、Big-Endian和Little-Endian转换
现有的平台上Intel的X86采用的是Little-Endian,而像Sun的SPARC采用的就是Big-Endian。那么在跨平台或网络程序中如何实现字节序的转换呢?这个通过C语言的移位操作很容易实现,例如下面的宏:
#if defined(BIG_ENDIAN) && !defined(LITTLE_ENDIAN)
#define htons(A) (A)
#define htonl(A) (A)
#define ntohs(A) (A)
#define ntohl(A) (A)
#elif defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN)
#define htons(A) ((((uint16)(A) & 0xff00) >> 8) | \
(((uint16)(A) & 0x00ff) << 8))
#define htonl(A) ((((uint32)(A) & 0xff000000) >> 24) | \
(((uint32)(A) & 0x00ff0000) >> 8) | \
(((uint32)(A) & 0x0000ff00) << 8) | \
(((uint32)(A) & 0x000000ff) << 24))
#define ntohs htons
#define ntohl htohl
#else
#error "Either BIG_ENDIAN or LITTLE_ENDIAN must be #defined, but not both."
Linux-Big-Endian和Little-Endian转换的更多相关文章
- c#,关于Big Endian 和 Little Endian,以及转换类
Big Endian:最高字节在地址最低位,最低字节在地址最高位,依次排列. Little Endian:最低字节在最低位,最高字节在最高位,反序排列. 当在本地主机上,无需注意机器用的是Big En ...
- 数据在内存中的存储方式( Big Endian和Little Endian的区别 )(x86系列则采用little endian方式存储数据)
https://www.cnblogs.com/renyuan/archive/2013/05/26/3099766.html 1.故事的起源 “endian”这个词出自<格列佛游记>.小 ...
- 大端和小端(Big endian and Little endian)
一.大端和小端的问题 对于整型.长整型等数据类型,Big endian 认为第一个字节是最高位字节(按照从低地址到高地址的顺序存放数据的高位字节到低位字节):而 Little endian 则相反,它 ...
- 大端和小端(big endian little endian)
一.大端和小端的问题 对于整型.长整型等数据类型,Big endian 认为第一个字节是最高位字节(按照从低地址到高地址的顺序存放数据的高位字节到低位字节):而 Little endian 则相反,它 ...
- 整型,长整型,无符号整型等 大端和小端(Big endian and Little endian)
一.大端和小端的问题 对于整型.长整型.无符号整型等数据类型,Big endian 认为第一个字节是最高位字节(按照从低地址到高地址的顺序存放数据的高位字节到低位字节):而 Little endian ...
- 字符编码笔记:ASCII,Unicode和UTF-8,附带 Little endian和Big endian的解释
作者: 阮一峰 日期: 2007年10月28日 今天中午,我突然想搞清楚Unicode和UTF-8之间的关系,于是就开始在网上查资料. 结果,这个问题比我想象的复杂,从午饭后一直看到晚上9点,才算初步 ...
- Endian.BIG_ENDIAN和Endian.LITTLE_ENDIAN(http://smartblack.iteye.com/blog/1129097)
Endian.BIG_ENDIAN和Endian.LITTLE_ENDIAN 在ByteArray和Socket中,能看到一个属性endain. endian : String 更改或读取数据的字节顺 ...
- 关于Big Endian 和 Little Endian
Big Endian 和 Little Endian 一.字节序 来自:http://ayazh.gjjblog.com/archives/1058846/ 谈到字节序的问题,必然牵涉到两大CPU派系 ...
- java代码中存在的Big Endian 和 Little Endian
Big Endian 和 Little Endian 详解 Java中的Big(Little)-endian问题的一种解决方法 主机序和网络序 很重要很重要 几种ip存放形式 Big-Endian和 ...
- Unicode、UTF-8、Big Endian、Little Endian、GBK、UCS-2
一.Unicode.UCS.GBK 1.开始计算机只在美国用.八位的字节一共可以组合出256(2的8次方)种不同的状态.把这些0×20以下的字节状态称为”控制码”.他们又把所有的空 格.标点符号.数字 ...
随机推荐
- FORM 提示保存
修改的FORM在编译到测试环境后打开并没有修改什么数据,却提示是否保存,检查->system.form_satus 为"changed": 个人实际解决情况为:在数据块级的触 ...
- Effective_Python mapreduce
完全吊炸天构造器的写法... import os import threading,time class GenericInputData(object): def read(self): raise ...
- 如何在Linux中查看所有正在运行的进程
如何在Linux中查看所有正在运行的进程 FROM:http://os.51cto.com/art/201101/244090.htm 进程是一个其中运行着一个或多个线程的地址空间和这些线程所需要的系 ...
- [充电]多线程无锁编程--原子计数操作:__sync_fetch_and_add等12个操作
转自:http://blog.csdn.net/minCrazy/article/details/40791795 多线程间计数操作.共享状态或者统计相关时间次数,这些都需要在多线程之间共享变量和修改 ...
- extjs 一些杂碎的技术问题
1怎样将grid 的checkedbox 勾选状态都清除 inv.getSelectionModel().clearSelections(); inv.getView().refresh(); 2怎样 ...
- python(七)字符串格式化、生成器与迭代器
字符串格式化 Python的字符串格式化有两种方式:百分号方式.format方式 1.百分号的方式 %[(name)][flags][width].[precision]typecode (name) ...
- WPFの静态资源(StaticResource)和动态资源(DynamicResource)
下面是前台代码: <Window.Resources> <TextBlock x:Key="res1" Text="好好学习"/ ...
- 2016年12月21日 星期三 --出埃及记 Exodus 21:16
2016年12月21日 星期三 --出埃及记 Exodus 21:16 "Anyone who kidnaps another and either sells him or still h ...
- CentOS7 运行级别
linux运行的级别7个级别运行级别的查看使用 runlevelrunlevelN 3 //运行在3级别,可以理解成命令行级别级别之间的切换需要使用init x 0 //关机3 //多用户的命令行级别 ...
- 编译安装php的配置参数详细解析
./configure --prefix=/usr/local/php --enable-opcache --enable-fpm --enable-sockets --enable-mysqlnd ...