彻底弄懂计算机中的大端小端

2023-05-16

大端与小端这个问题在做和其他设备交换原始字节数据的时候是非常重要的概念,也是必须要掌握的内容,但是很多人就是仅仅是稍微有些了解,但每次真正去做东西的时候,还是要花半天去想,博主就是这样的人,出现这样问题的真正原因是还没有完全弄清楚大端小端。今天就让我们一起彻底的弄懂这两个东西吧!

先讲讲关于这两个东西的传说吧(也是抄来的^_^)

“大端”和“小端”可以追溯到1726年的Jonathan Swift的《格列佛游记》,其中一篇讲到有两个国家因为吃鸡蛋究竟是先打破较大的一端还是先打破较小的一端而争执不休,甚至爆发了战争。1981年10月,Danny Cohen的文章《论圣战以及对和平的祈祷》(On holy wars and a plea for peace)将这一对词语引入了计算机界。这么看来,所谓大端和小端,也就是big-endian和little-endian,其实是从描述鸡蛋的部位而引申到计算机地址的描述,也可以说,是从一个俚语衍化来的计算机术语。稍有些英语常识的人都会知道,如果单靠字面意思来理解俚语,那是很难猜到它的正确含义的。在计算机里,对于地址的描述,很少用“大”和“小”来形容;对应地,用的更多的是“高”和“低”;很不幸地,这对术语直接按字面翻译过来就成了“大端”和“小端”,让人产生迷惑也不是很奇怪的事了。

我希望这篇文章的读者起码要知道大端小端是干什么的,不然看了效果也不会很好

一个句话解释什么是大端,什么是小端
在用英文属于解释就是,most significant (最高有效位)在低地址位就是大端,(least significat) 在高地址位就是小端,看完这句话,你是不是清楚了什么是大端,什么是小端了呢? 正常人的反应会是,哎呀,我操,这都是些啥啊?不但没有更清楚,反而更晕了,我开始看到这样的解释也是这样的反应。

再来一个问题,彻底搞晕你(放心,我会把你搞清醒的^__^)

示例用C来描述

1short num1 = 0x12FF;
例2char * str1 = "abcde";
例3 :数字32short 十六进制: 00 20

请问上面的代码中 例1 是大端还是小端 , 例2 是大端还是小端,例3 是大端还是小端 ,我希望到这里我已经成功的将你 搞晕 了。


根本原则,大端小端是针对于存储而言的,和字面的表达方式没关系


    所以之前我提的问题全是些伪命题,而计算机中大端小端真正的含义要在存储中讲才能讲明白。
    我们先来看例1 ,我们都知道在C中short 占用两个字节,我们这里给这两个字节赋值为0x12 和0xFF,在计算机中内存是一个个的字节单元。

    好了问题又来了,这两个字节在内存中是如果放的呢,假如 num1的 起始地址是 0x0056A100, 那么存放num1内容的应该是 0x0056A100和0x0056A101,但是哪个是0x12 ,哪个是0xFF呢? 我们写一段代码来看一下

int main(int argc, _TCHAR* argv[]){

    unsigned short num1 = 0x12FF;
    char * address = (char *)&num1;

    printf("low bytes is %x , high bytes is %x",*address & 0xFF,  *(address + 1) & 0xFF );
    }

程序很简单,就是分别打印两个字节的内容,低字节是address,高字节是address+1 , 我们来看一下 运行结果
这里写图片描述

    可以看到低位地址是0xFF高位是0x12,num1 这个数的高位12 存在了内存的低地址处,低位FF存在高地址处, 所以我们的机器 是小端的机器,其实只要确定内存的低地址存放的是高位还是低位就行了,这里低地址是0xFF(低位),所以是小端。代表我们的机器是小端机器,严格的说是CPU处理数据的方式采用的是小端法。

字符串中又是怎样的情况呢?

char * a = “abcd”;

#

其实在程序中字符串并没有大端小端并之说,只有在涉及到数据的传输时,字符串的大端小端才值的注意,我们后面会探讨这一问题,但很多教材或者是博客都直接把整型和字符串的大小端放在一起讲,就容易更让人搞不清楚。这里的d肯定是存放在高地址,a肯定是存放在低地址。

大端小端和字符串没有任何关系


网络中的大端与小端

可能上面的内容你已经搞清楚了,但是当你看一些关于网络或者的资料时发现又有什么网络字节序神马的,然后又糊涂了,让我们一起来破除关于网络字节序列这些神马的浮云。

-了解网络是怎样发送数据的?

我们使用的网络协议很多都是基于socket的,所以我们基于socket来讲,在socket规范中发送数据是 这个方法

send(Socket soc, char * buf, len , 0);
第一个参数是对方的socket,也就是地址
第二个参数是 一个字符指针,也就是要发送的内容存放的地址
第三个是发送数据的长度
第四个是和选择协议相关的,一般设为0

所以这里我们看到在底层发送数据的方法里面根本没有和什么大端小端有关系的东西,发送的函数只关心你要老子发送的东西在哪儿,发多少,其他一概不管,好,现在用一个场景说明一下。程序员A把一个金额发给程序员B,这个金额是B欠A钱的金额。

//A发给B,这是B欠我A的数目 ,是1500元,下面是十六进制写法
short a = 0x05DC;
//于是A就
send(sock, (char *)&a,2,0);

接收和发送的函数方法参数是一样的
recv(Socket soc, char * buf, len , 0);
好,这个数目发完了,B接收的时候用下面的代码

char ownMoney [2];
recv(Socket soc,ownMoney, 2 , 0);

好了,数据发送和接受都完成了,到这里为止,和大小端半毛钱关系都没有,接下来就有了。这B想看看到底欠了A多少钱了,用下面的代码接收。

int total = ((ownMoney[0] << 8) | (ownMoney[1] & 0xFF )   &0xFF );

一看吓了一跳 56325,这就出大问题了,B心想,A是我铁哥们儿,肯定不会骗我,肯定是那个地方数据出错了,于是有了下面的对话

B:兄弟你电脑CPU是什么的?
A:是intel的啊
B:发送数据的时候有做什么处理吗?
A:没有做任何处理
B:额,我明白了

刚好B的机器也是Intel的CPU,B找到原因之后背了一遍我编写的口诀,低地址是低位是小端,低低地址是高位为大端。

B分析了一下数据的发送流程,A发送两个字节的short型数据,因为A是小端所以,先发送过来的是低位数据,后发送的是高位,我先接收的也是低位,后接收的是高位。

B修改程序后

int total = (ownMoney[0]  &0xFF ) | ( (ownMoney[1] << 8) & 0xFF )   );

一看,额,1500,心里松了一口气,这就对了。我们来看看出现刚刚这个问题的原因。
A是 Intel CPU (小端机器), 0x05DC这个数,低地址存放的是DC,高地址是05, B接受了放在 字符数组中, 因为B也是小端机器,B还原数据的时候是在低地址放在了高位,也就是0xDC,这是 不对的。

那总不能每次发送数据都问一下别人是什么CPU吧?

于是人们就约定将数据的低地址处放数据的高位(也叫大端法),于是A就遵循了这个约定, 发送之前将数据位置改了一下,因为之前低地址放的是低位。之前A的数据是这样放的

低地址高地址
DC05



因为约定采用大端法发送数据,所以要改成下面这样

低地址高地址
05DC


//这样改变位置的代码
short a = 0x05DC;
//用一个字符指针指向a 
char* pointerOfA = (char *)&a;

//把数据的低位值保存在一个变量里,也就是 DC
char temp = *(pointerOfA );
//把高位的值放在低位 
*pointerOfA = *(pointerOfA +1);
*(pointerOfA +1) = temp;

//再发送
send(sock, pointerOfA ,2,0);

如果遵守约定,B就不用问A你的机器是什么类型了,但是还有一个问题,因为B的机器类型可能是大端也可能是小端,那接受数据的时候还要去判断机器类型,这也太麻烦了,对,没错,底层的网络处理就是这么麻烦。

让世界更美好

这个世界变得越来越美好,是因为有前人无私的付出,计算机的世界也一样,在大小端数据转换中也有实现好了的函数,只等着你去调用。

htons(unsigned short  n):将short转为网络字节序
htonl(unsigned long n) : 将long转为网络字节序

htons 意思就是host to network ,后面一个代表数据类型

还有从网络字节序转成本机字节序的方法

ntohl 
ntohs

先就将到这里,如有错误,请大家批评

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

彻底弄懂计算机中的大端小端 的相关文章

  • Qt 之 设置窗口边框的圆角

    Qt技术学习班开始了 xff0c 更多精彩 好玩的内容等着你 xff0c 赶紧报名吧 群号 xff1a 655815739 Qt在设置窗口边框圆角时有两种方式 xff0c 一种是设置样式 xff0c 另一种是在paintEvent事件中绘制
  • Qt 之 HTTP 请求下载(支持断点续传)

    简述 最近在研究了一下用Qt 的方法来实现http下载 xff0c Qt 中的Http请求主要用到了QNetworkAccessManager QNetworkReply QNetworkRequest 这三块 本篇文章主要叙述如何用Qt
  • Qt之实现录音播放及raw(pcm)转wav格式

    简述 在上一篇 Qt 之 WAV文件解析 中详细地分析了wav格式文件的文件头信息 通过QAudioInput实现录音功能 xff0c 但是录音生成的文件并不能用播放器打开 xff0c 就算更改后缀名也无法识别 xff08 有时候下载的一些
  • C++中 Unicode 与 UTF-8 编码互转

    1 简述 最近在发送网络请求时遇到了中文字符乱码的问题 xff0c 在代码中调试字符正常 xff0c 用抓包工具抓的包中文字符显示正常 xff0c 就是发送到服务器就显示乱码了 xff0c 那就要将客户端和服务器设置统一的编码 xff08
  • Qt 之 自定义按钮 在鼠标 悬浮、按下、松开后的效果

    Qt技术学习班开始了 xff0c 更多精彩 好玩的内容等着你 xff0c 赶紧报名吧 群号 xff1a 655815739 一 简述 在上一篇 Qt 之 去除窗口部件被选中后的焦点虚线框 中 xff0c 我们为了去除焦点虚线框 xff0c
  • Qt 之 自定义窗口标题栏

    Qt训练营开始了 xff0c 更多精彩 好玩的内容等着你 xff0c 赶紧报名吧 群号 xff1a 861353824 一 简述 今天晚上就如何用Qt自定义窗口标题栏 xff0c 写了一个小例子 xff0c 比较基础 xff0c 实用 在此
  • Qt 之 模仿 QQ登陆界面——旋转窗口篇

    一 简述 今天是新的一年第一篇博客 xff0c 有大半个月没有更新博客了 我想是时候 xff0c 打开电脑 拿起键盘 开始在我的代码之路上披荆斩棘 xff0c 斩杀恶龙 今天就继续来分享QQ登录界面的那些事 QQ登录界面的标题栏有一个小三角
  • Ubuntu配置无线路由器笔记记录

    参考文章 xff1a linux 开启制作无线路由器 ubuntu 1404 linux zhu的博客 CSDN博客 hostapd实现WIFI 热点 xff08 AP xff09 自由枫 的博客 CSDN博客 hostapd 终端get一
  • C++STL的使用心得汇总(vector,string,map,list)

    文章目录 find 函数vector的findstring的findmap的find count 函数vector的countstring的countmap的count vectorstringmap的各种排序方法转换相关 待完善 find
  • Qt 之 样式表的使用——设置样式的方法

    一 简述 我们通常在使用Qt开发的过程中都会使用样式表来美化我们的界面 xff0c 关于如何使用样式表的资料也很多 xff0c 样式表的使用方法也千变万化 为了搭建一个漂亮的界面那么必须学会如何使用样式表 xff0c Qt帮助文档中提供了非
  • 如何使QGraphicsItem不随QGraphicsView放大缩小而改变大小

    一 简述 在使用QGraphicsView过程中 xff0c 有时候我们需要对view进行缩放 xff0c 但是对于一般正常的加入view中的item都会随着view的大小变化而变化 xff0c 但是如果我们想让某些item不随view的缩
  • 【linux系统如何查看内核版本、操作系统版本等信息】

    有时候需要查看linux系统的内核版本 xff0c 可以有多种方法 xff0c 方法如下 xff1a xff08 下面以优麒麟系统为例 xff09 方法1 xff1a 打开mate终端 xff0c 在命令行输入以下命令 xff1a unam
  • 【linux系统如何安装arm交叉编译工具链】

    文章目录 前言一 arm交叉编译器介绍命名规则具体编译器 二 Arm GNU Toolchain安装总结 前言 本文简要介绍arm交叉编译器及工具链的安装方法 一 arm交叉编译器介绍 命名规则 交叉编译工具链的命名规则为 xff1a ar
  • 比较冒泡排序、选择排序和快速排序的时间(C语言实现)

    文章目录 前言代码设计代码实现运行结果结果分析稳定性测试 总结 前言 本文主要比较冒泡排序 快速排序 选择排序的时间 冒泡排序和快速排序的思想可以参考我转载的以下博文 xff1a https blog csdn net gogo0707 a
  • freertos应用程序常见错误排查

    freertos系统应用程序常见问题 对一些比较常见的问题 xff0c 下面简要的以 FAQ 问答 的形式给出可能的原因和解决方法 问题现象 xff1a 在一个 Demo 应用程序中增加了一个简单的任务 xff0c 导致应用程序崩溃 任务创
  • keil5编译工程常见问题汇总

    简介 我们在编译keil工程的时候总是遇到很多问题 xff0c 我把一些常见的问题和解决方案汇总下来 xff0c 仅供大家参考 问题汇总 问题1 问题描述 选择arm v6版本编译器 xff0c 编译keil5工程 xff0c 报错 xff
  • mdk arm debug配置

    简述 本文简要讲述启动调试之前如何配置debug 点击魔术棒 xff0c 进入debug选项界面 xff0c 如下图 xff1a 我们可以选择软件仿真 xff0c 也可以选择硬件仿真 xff08 软件仿真不需要接开发板和仿真器 xff09
  • stm32高级定时器实现pwm互补输出

    简介 stm32设备一般都有很多类型的定时器 xff0c 常见的有systick timer 基本定时器 通用定时器 高级定时器 看门狗定时器 RTC等等 xff0c 本文简单介绍高级定时器是如何实现pwm互补输出 详细 我这里使用的dev
  • shell脚本基础知识(入门)

    简介 本文会全面介绍shell脚本的基础知识 脚本格式 要把shell命令放到一个 脚本 当中 xff0c 有一个要求 xff1a 脚本的第一行必须写成类似这样的格式 xff1a bin bash bash是一个shell解释器 xff0c
  • 记ADB shell for循环踩坑

    abd 里面的shell的电脑Linux的shell有点不太一样 以下这些案例均不能执行 xff1a for i 61 1 i lt 61 100 i 43 43 do echo i done for i in 1 100 do echo

随机推荐

  • linux线程调度策略简述

    简述 linux系统调度执行的最小单位是线程 xff0c 线程的调度策略有以下三种 xff1a xff08 1 xff09 SCHED FIFO 其静态优先级必须设置为1 99 xff0c 这将意味着一旦线程处于就绪态 xff0c 他就能立
  • stm32串口发送接口

    简介 本文记录一下stm32标准库实现串口发送功能和接收功能的接口函数 轮询方式发送串口数据 1 标准库实现 span class token comment 61 61 61 61 61 61 61 61 61 61 61 61 61 6
  • linux系统线程池

    简述 一个进程中的线程就好比是一家公司里的员工 xff0c 员工的数目应该根据公司的业务多少来定 xff0c 太少了忙不过来 xff0c 但是太多了也浪费资源 最理想的情况是让进程有一些初始数目的线程 xff08 线程池 xff09 xff
  • STM32串口环形缓冲区

    目录 1 xff1a 概述 2 xff1a 代码 1 xff1a 概述 1 1 xff1a 本篇实现串口驱动 xff0c 实现printf函数的重定向 xff0c 实现串口的中断接受和发送 xff0c 效仿modbus协议中的3 5T超时机
  • 天地飞6通道遥控器解码

    在做四轴 xff0c 想到要改造一下遥控器 我用的是天地飞6通道2 4G版 改造的思路是这样的 xff1a 用M8单片机读取PPM信号 xff0c 用液晶显示出6个通道的解码 xff0c 当然这个解码还需要根据飞控板进行一下 校准 xff0
  • 如何计算网络协议校验和以及为什么这么计算

    一 校验和是如何计算的 xff1f 这个问题牵扯到计算机最底层最神秘的部分 二进制运算 说实话 xff0c 从学计组计统起 xff0c 我就比较讨厌思考二进制的相关运算 但毕竟是学这个的 xff0c 只好硬着头皮想了 首先发送方校验和的计算
  • JAVA又臭又长,是一门垃圾语言,早晚会被淘汰

    1 JAVA又臭又长 xff0c 是一门垃圾语言 xff0c 早晚会被淘汰 2 JAVA能做的 xff0c python 等上层解释类语言大部分都可以坐到 3 JAVA为了面向对象而面向对象 xff0c 导致程序冗长 xff0c 效率低下
  • 封装OkHttp

    懒汉 安全 加同步 私有的静态成员变量 只声明不创建 私有的构造方法 提供返回实例的静态方法 private static OkHttpClient okHttpClient 61 null private OkHttp3Util publ
  • WXP380 电容式MEMS高性能数字气压传感器 电容式MEMS压力传感器快速代DPS310 BMP380 SLP06 HP303B “电容式”噪声超低的高精度MEMS气压传感器;

    午芯高科WXP380气压传感器 稳定供应 填补国内空白 2 WXP380气压传感器的 电容式 MEMS芯片填补了国内技术空白 xff01 高性能 xff1a 电容式 噪声超低的高精度MEMS气压传感器 xff1b 高度差测量精确度小至2cm
  • 解决ros的rosdep update报错的问题。

    参见以下文章 xff1a https blog csdn net leida wt article details 115120940 如果 xff1a https raw githubusercontent com ros rosdist
  • Docker报错Error spawning command line “dbus-launch --autolaunch=xxx --binary-syntax --close-stderr”

    环境 xff1a ubuntu 18 报错描述 xff1a Error spawning command line dbus launch autolaunch 61 a3d9197b765643568af09eb2bd3e5ce7 bin
  • 一种测量STM32程序执行时间的方法

    同名微信公众号 固件工人 同步发布的文章 xff0c 欢迎同时关注 xff0c 及时获取最新文章 1 1 背景 在单片机的固件开发过程中 xff0c 有的时候需要评估固件代码的执行性能 xff0c 会对部分关键程序代码的执行时间进行测量 通
  • STM32使用内核System Tick定时器实现微秒延时

    同名微信公众号 固件工人 同步发布的文章 xff0c 欢迎同时关注 xff0c 及时获取最新文章 在单片机的程序开发中 xff0c 延时一般都会用到 xff0c 在对延时精度要求不高的场合 xff0c 一般使用软件延时实现 xff0c 就是
  • STM32软件模拟I2C从机的实现方法

    1 1 前言 在使用I2C通信时 xff0c 一般会用到软件模拟I2C 目前网络上能搜索到的软件模拟I2C一般都是模拟I2C主机 xff0c 很少有模拟I2C从机的例程 由于I2C主机在进行数据收发时 xff0c 有明确的可预见性 xff0
  • Ubuntu下QT创建带菜单和工具栏的窗口

    同名微信公众号 固件工人 同步发布的文章 xff0c 欢迎同时关注 xff0c 及时获取最新文章 1 1 测试平台 这里使用的开发环境如下 操作系统 xff1a Ubuntu 20 04 2 LTS x86 64 xff08 使用uname
  • wxWidgets学习:Ubuntu下cmake编译链接wxWidgets源码报错[Could NOT find GSTREAMER]

    同名微信公众号 固件工人 同步发布的文章 xff0c 欢迎同时关注 xff0c 及时获取最新文章 1 测试平台 这里使用的开发环境如下 操作系统 xff1a Ubuntu 20 04 2 LTS x86 64 xff08 使用uname a
  • VS2012 C++/CLR 无法创建Windows窗体应用程序的解决方法

    参考资料链接 xff1a 1 https zhidao baidu com question 493819968 html 2 http blog csdn net dreamrabbit article details 9044999 在
  • VC中自定义打印调试信息函数,打印调试信息到DebugView上

    该文档参考了以下网友的文章 xff0c 在此表示感谢 1 xff08 更新 xff09 OutputDebugString函数简单封装 xff0c 实现格式化打印输出 xff08 VC 43 43 xff09 链接 xff1a http b
  • C语言编译器之三,VC++

    三 Visual C编译器 Microsoft Visual C 43 43 xff08 简称Visual C 43 43 MSVC VS或VC xff09 是微软公司的免费C 43 43 编译器与开发工具 xff0c 具有集成开发环境 x
  • 彻底弄懂计算机中的大端小端

    大端与小端这个问题在做和其他设备交换原始字节数据的时候是非常重要的概念 xff0c 也是必须要掌握的内容 xff0c 但是很多人就是仅仅是稍微有些了解 xff0c 但每次真正去做东西的时候 xff0c 还是要花半天去想 xff0c 博主就是