1.大小端定义

大端存储模式:是指数据的低位字节序保存在内存的高地址中,而数据的高位字节序保存在内存的低地址中
小端存储模式:是指数据的低位字节序保存在内存的低地址中,而数据的高位字节序保存在内存的高地址中

例如:16bit宽的数0x0001在CPU内存中的存放方式(假设从地址0x4000开始存放)为:

内存地址 0x4000 0x4001
存储内容(大端) 0x00 0x01
存储内容(小端) 0x01 0x00

大端模式,是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放;这和我们的阅读习惯一致。

小端模式,是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低。

对于0x11223344 储存如下:

2.为什么会有大小端之分

这是因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为8bit。但是在C语言中除了8bit的char之外,还有16bit的short型,32bit的long型(要看具体的编译器),另外,对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如果将多个字节安排的问题。因此就导致了大端存储模式和小端存储模式。

例如一个16bit的short型x,在内存中的地址为0x0010,x的值为0x1122,那么0x11为高字节,0x22为低字节。对于大端模式,就将0x11放在低地址中,即0x0010中,0x22放在高地址中,即0x0011中。小端模式,刚好相反。

我们常用的X86结构是小端模式,而KEIL C51则为大端模式。很多的ARM,DSP都为小端模式。有些ARM处理器还可以由硬件来选择是大端模式还是小端模式。

3.数据存储

首先,我们看一下数据在内存是怎么存储的

从上边我们可以看出a、b在计算机中存储的是补码,但是顺序却倒着的,这实际上就是小端存储。

程序中一个变量的地址是指这个变量的起始地址,也就是低地址。例如 4字节 int 型变量的地址就是变量的起始地址,即这4字节变量对应的地址空间中的最低地址。

网络字节序

程序中一个变量的地址是指这个变量的起始地址,也就是低地址。例如 4字节 int 型变量的地址就是变量的起始地址,即这4字节地址空间中的最低地址。
而网络发送时,是从起始地址开始操作处理变量数据的,因此会先传输变量的低地址数据,后传输高地址数据。

网络上传输的数据都是字节流,对于一个多字节数值,在进行网络传输的时候,先传递哪个字节?也就是说,当接收端收到第一个字节的时候,它将这个字节作为高位字节还是低位字节处理,是一个比较有意义的问题;
  UDP/TCP/IP协议规定:把接收到的第一个字节当作高位字节看待,这就要求发送端发送的第一个字节是高位字节;而在发送端发送数据时,发送的第一个字节是该数值在内存中的起始地址处对应的那个字节,也就是说,该数值在内存中的起始地址处对应的那个字节就是要发送的第一个高位字节(即:高位字节存放在低地址处);由此可见,多字节数值在发送之前,在内存中因该是以大端法存放的;
  所以说,网络字节序是大端字节序;
  在实际中,当在两个存储方式不同的主机上传输时,需要借助字节序转换函数。

1、什么是大小端模式?

大端模式:是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中。

小端模式:是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中。

举个栗子:

比如数字 0x12 34 56 78在内存中的表示形式为:

  • 大端模式
    低地址 -----------------> 高地址

0x12 | 0x34 | 0x56 | 0x78

  • 小端模式
    低地址 ------------------> 高地址

0x78 | 0x56 | 0x34 | 0x12

可见,大端模式和字符串的存储模式类似。

2、知道大小端有何用?

首先要介绍一下字节序列,所谓的字节序列就是大于或者等于两个字节类型的数据存放在内存中的顺序(一个字节就不必谈序列!)。那么什么时候要用到我们去判断机器是大端模式还是小端模式呢?当我们在跨平台开发或者网络编程的时候就要去关心字节序列了,比如说我们用机器A和B通信,如果A和B的端序都是一样的话,中间自然就不用转换来转换去了。但是如果A和B机器的端序不一样,如果我们不去做相应的转换,我们传过去的二进制序列就是反的!

3、大端小端没有谁优谁劣,各自优势便是对方劣势:

小端模式 :强制转换数据不需要调整字节内容 。

大端模式 :符号位的判定固定为第一个字节,容易判断正负。

4、为什么会有大小端模式之分呢?

这是因为在计算机中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为 8 bit。但是在C 语言中除了 8 bit 的char之外,还有 16 bit 的 short型,32bit的long型(要看具体的编译器),另外,对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如果将多个字节安排的问题。因此就导致了大端存储模式和小端存储模式。例如一个16bit的short型 x ,在内存中的地址为 0x0010,x 的值为0x1122,那么0x11位高字节,0x22位低字节。对于大端模式,就将0x11放在低地址中,即0x0010中,0x22放在高地址中,即0x0011中。小端模式,刚好相反。我们常用的X86结构是小端模式,而KEIL C51则为大端模式。很多的ARM,DSP都为小端模式。有些ARM处理器还可以由硬件来选择是大端模式还是小端模式。

一般操作系统都是小端,而通讯协议是大端的

5、如何去判断机器是大端模式还是小端模式?

1 ) 代码实现 :编译环境 VC++6.0 结果输出为 小端存储

#include "stdafx.h"
bool IsBigEndian1()
{  int a = 1;  //00 00 00 01//通过将int强制类型转换成char单字节,通过判断起始存储位置。即等于 取b等于a的低地址部分char b =  *(char *)&a; /* char b = *(char*)&a;这句话到底干了什么事呢?详解:&a是通过'&'取地址符获取到了a的地址或者可以认为是个指向int类型数据的指针(char *)&a 则把&a强制转换成 char *类型的指针,本句重点就是这个时候发生了截断!<因为还未深入学习指针所以此处对为何发生截断不予详细解释,等后续系统学习后再做补充>截断后,指针(char *)&a 内存放的是存放‘1’的低地址,也就是说此处指向的数值 即b仅为原 始数据的一部分。因为已经确定 是低地址,所以可以通过此处地址指向的数值来判断此环境的存储模式是大端还是小端如果b = 0 即 低地址存放高位数据 则为大端模式如果b = 1 即 低地址存放低位数据 则为小端模式*///printf("b=%0x\n",b); 此句如果被注释  将会输出 b=34 以此更直观的看到效果if( b == 0)  {  return true;  }  return false;
}
int main(int argc, char* argv[])
{if(IsBigEndian1()==true){printf("大端存储\n");}else{printf("小端存储\n");}return 0;
}

2)联合体union的存放顺序是所有成员都从低地址开始存放,利用该特性可以轻松地获得了CPU对内存采用Little-endian还是 Big- endian模式读写:

  • 算法思路:定义一个联合体,根据联合体成员起始地址相同巧妙的访问到了第一个字节地址的数据。
  • 联合体类型特点:
#include "stdafx.h"
/*
联合体union的存放顺序是所有成员都从低地址开始存放,利用该特性
可以轻松地获得了CPU对内存采用Little-endian还是Big-endian模式读写:
*/
bool IsBigEndian2()
{  union NUM  {  int a;  char b;  }num;  num.a = 0x1234;  if( num.b == 0x12 )  {  return true;  }  return false;
}
int main(int argc, char* argv[])
{if(IsBigEndian2()==true){printf("Big-endian\n");}else{printf("Little-endian\n");}return 0;
}

6.常见字节序:

常见CPU的字节序

Big Endian : PowerPC、IBM、Sun
Little Endian : x86、DEC
ARM既可以工作在大端模式,也可以工作在小端模式。

常见文件的字节序

Adobe PS – Big Endian
BMP – Little Endian
DXF(AutoCAD) – Variable
GIF – Little Endian
JPEG – Big Endian
MacPaint – Big Endian
RTF – Little Endian

另外,在C语言中,默认是小端(但在一些对于单片机的实现中却是基于大端,比如Keil 51C),Java是平台无关的,默认是大端。在网络上传输数据普遍采用的都是大端。

7.多角度理解

1.从软件的角度上,不同端模式的处理器进行数据传递时必须要考虑端模式的不同。如进行网络数据传递时,必须要考虑端模式的转换。 在对普通文件进行处理也需要考虑端模式问题。在大端模式的处理器下对文件的32,16位读写操作所得到的结果与小端模式的处理器不同。单纯从软件的角度理解上远远不能真正理解大小端模式的区别。事实上,真正的理解大小端模式的区别,必须要从系统的角度,从指令集,寄存器和数据总线上深入理解,大小端模式的区别。

2.从系统的角度上,处理器在硬件上由于端模式问题在设计中有所不同。从系统的角度上看,端模式问题对软件和硬件的设计带来了不同的影响,当一个处理器系统中大小端模式同时存在时,必须要对这些不同端模式的访问进行特殊的处理。如果从实际应用的角度说,采用小端模式的处理器需要在软件中处理端模式的转换,因为采用小端模式的处理器在与小端外设互连时,不需要任何转换。而采用大端模式的处理器需要在硬件设计时处理端模式的转换。大端模式处理器需要在寄存器,指令集,数据总线及数据总线与小端外设的连接等等多个方面进行处理,以解决与小端外设连接时的端模式转换问题。在寄存器和数据总线的位序定义上,基于大小端模式的处理器有所不同。

3.实际例子

虽然很多时候,字节序的工作已由编译器完成了,但是在一些小的细节上,仍然需要去仔细揣摩考虑,尤其是在以太网通讯、MODBUS通讯、软件移植性方面。这里,举一个MODBUS通讯的例子。在MODBUS中,数据需要组织成数据报文,该报文中的数据都是大端模式,即低地址存高位,高地址存低位。假设有一16位缓冲区m_RegMW[256],因为是在x86平台上,所以内存中的数据为小端模式:m_RegMW[0].low、m_RegMW[0].high、m_RegMW[1].low、m_RegMW[1].high……
为了方便讨论,假设m_RegMW[0] = 0x3456; 在内存中为0x56、0x34。

现要将该数据发出,如果不进行数据转换直接发送,此时发送的数据为0x56,0x34。而Modbus是大端的,会将该数据解释为0x5634而非原数据0x3456,此时就会发生灾难性的错误。所以,在此之前,需要将小端数据转换成大端的,即进行高字节和低字节的交换,此时可以调用步骤五中的函数BigtoLittle16(m_RegMW[0]),之后再进行发送才可以得到正确的数据。

大小端(网络字节序)等概念相关推荐

  1. 大小端模式 字节序

    大.小端模式的说法,来自乔纳森·斯威夫特的小说<格列夫游记>,在小人国内部分裂成 Big-endian 和 Little-endian 两派,他们的争论在于一派要求从鸡蛋的大头把鸡蛋打破, ...

  2. 大小端以及字节序的问题

    网络字节顺序NBO(Network Byte Order):按从高到低的顺序存储,在网络上使用统一的网络字节顺序,可以避免兼容性问题. The order in which the bytes of ...

  3. 网络传输大端序_大端、小端与网络字节序

    大端(Big-Endian),小端(Little-Endian)以及网络字节序的概念在编程中经常会遇到.网络字节序(Network Byte Order)一般是指大端(Big-Endian,对大部分网 ...

  4. Linux网络编程——字节序与网络字节序

    说明:   本文章旨在总结备份.方便以后查询,由于是个人总结,如有不对,欢迎指正:另外,内容大部分来自网络.书籍.和各类手册,如若侵权请告知,马上删帖致歉.   QQ 群 号:513683159 [相 ...

  5. c# 网络字节序数据传输

    之前写过一篇python的十六进制数据传递与接收,介绍了网络字节序等概念,这里就不在赘述了,下面主要介绍下c#下怎么进行网络字节序的发送与接收. 1.stuct结构体 在python中使用到了stru ...

  6. linux大端小端命令,linux的大小端、网络字节序问题

    linux的大小端.网络字节序问题 总结:1.80X86使用小端法,网络字节序使用大端法. 2.二进制的网络编程中,传送数据,最好以unsigned char, unsigned short, uns ...

  7. 什么是字节序(端序、低端字节序、高端字节序、网络字节序)

    前言 一个内容为12(字符串)的文本文件,它的第一个字节是什么(小端序)?如果你的回答是0x32,那你真的应该好好理解下字节序了.如下图所示,我这里的正确答案是0x31.当然如果你的回答是不一定,这似 ...

  8. 网络基础1--计算机网络背景-局广城网范围,还有其他各种网,交换机路由器概念,ip地址,mac端口了解,网络协议,五层模型,传输中数据封装和分用,网络字节序,主机字节序如何判断。

    ** 计算机网络背景 ** 网络发展史:一个网络由路由器星形发散 局域网 1.指覆盖范围在1000米以内的网络 2.计算机的数量较多,通过交换机和路由器连在一起,也被称为服务器. 城域网: 1.指覆盖 ...

  9. linux网络编程之网络字节序、主机字节序、大端、小端

    1.主机字节序介绍 不同的CPU有不同的字节序类型 这些字节序是指整数在内存中保存的顺序 这个叫做主机字节序,存储方式有2种 1).大端模式 大端模式(Big-Endian)就是高位字节排放在内存的低 ...

最新文章

  1. 使用ARouter实现组件化
  2. FreeRTOS任务优先级
  3. 视频丨包不同的沙雕敏捷之砸锅卖铁买兰博
  4. c语言因子优化算法,【代码】求一个数的因数和、求优化、顺便也供新人参考算法...
  5. 文件io(二)--unix环境高级编程笔记
  6. (转载)PHP环境搭建-记录
  7. oracle为表空间增加数据文件_只读数据文件损坏恢复实验记录
  8. Momentum动量法
  9. php 到处excel 乱码,php 导出excel 乱码怎么办
  10. (ICPR-2021)使用胶囊的多尺度部分表示变换的步态识别
  11. Windows XP 下如何用 Modem 发传真
  12. linux中iptable和firewalld详解
  13. html微博登录代码,微博第三方登陆js实现
  14. oracle cube,oracle rollup和cube分析
  15. linux 彻底删除oracle,Linux下完美卸载Oracle
  16. windows飞行模式被强制开启,无法关闭,我来带你解决问题
  17. [课业] 25 | 数据库基础 | 基础SQL查询语言
  18. [Linux] 添加清华镜像
  19. 我的世界(9)-服务器地图创建、管理(Multiverse插件)
  20. 12款好用的Visual Studio插件,最后一款良心推荐

热门文章

  1. 中国力量的崛起:扒一扒新一代国际视频编码标准背后的“无限战争”
  2. 李恩齐受邀参加2021《巴黎时装周儿童单元·圣诞特别活动》
  3. 寻找0XCC软件断点
  4. 醉翁之意不在酒?Iceberg Research宣布做空AMC,但散户们却不买账
  5. 演唱会荧光棒场控原理
  6. 公司服务器内网OA网站如何实现外网访问?
  7. AI 写作助手,快速轻松地制作引人入胜的内容! #BlogNLP
  8. 题目:信用卡还款是银行系统的重要业务,业务流程说明如下:用户有信用卡和储蓄卡,储蓄卡有查询余额和取款功能,信用卡能够查看账单金额、查看还款日和查看余额三个功能;
  9. 在js中为对象添加和删除属性
  10. 盘片、片面、磁头、扇区、磁道的关系