PS:要转载请注明出处,本人版权所有。

PS: 这个只是基于《我自己》的理解,

如果和你的原则及想法相冲突,请谅解,勿喷。

前置说明

  本文作为本人csdn blog的主站的备份。(BlogID=089)

  本文发布于 2019-11-04 16:44:48,现用MarkDown+图床做备份更新。blog原图已丢失,使用csdn所存的图进行更新。(BlogID=089)

环境说明

  无

背景


  出来工作了两年有余了,其中有很多次接触到大小端的问题,每次都是拍一下脑袋,按照记忆中的内容做东西。(小端:高地址存高字节,低地址存低字节;大端:高地址存低字节,低地址存高字节)没有做深入的理解,导致我最近遇到一个通信接口文档,文档标注的是大端模式,但是我按照自己的记忆中的大端去做,却写错了,这不是我记忆有问题,只是我没有理解到位而已。

Big endian And Little endian(大小端)


  在多个字节读写或者传输过程中,哪个字节作为高字节,哪个字节作为低字节,需要我们人为定义的。于是人们定义了大端模式和小端模式。但是我们常见的一句话:“小端:高地址存高字节,低地址存低字节;大端:高地址存低字节,低地址存高字节。”是指的多字节存储中的定义。对于多字节传输中,大端小端这样记忆或者说理解可能会出问题。

#include <iostream>
#include <iomanip>
#include <cstdint> union test_byte_order{ uint16_t a;
uint8_t b;
}test0; int main(int argc, char * argv[]){ test0.a = 0xAAFF; //byte-order-check based on union
//Notice that the basefield flag only affects the insertion/extraction of integer values (floating-point values are always interpreted in decimal base).
std::cout<<"addr of test0.a is "<<std::hex << (uint64_t)&test0.a <<std::endl;
std::string union_ret = (test0.b == 0xFF)?"little endian":"big endian";
std::cout<<union_ret<<std::endl; //byte-order-check based on pointer
uint16_t a = 0xAAFF;
uint8_t * b = (uint8_t *)&a;
std::cout<<"addr of a is "<<std::hex << (uint64_t)&a <<std::endl;
std::string pointer_ret = (*b == 0xFF)?"little endian":"big endian";
std::cout<<pointer_ret<<std::endl; return 0;
}

  gdb调试结果(符合预期)

  常见的x86 是小端模式

  现在常见的arm 支持大小端模式

多字节通信(人为约定)

  多字节通信的问题的话,其实就是你是先发送高字节,还是先发送低字节位的问题。其实如果通信文档中一般都定义了先发送高还是低字节,但是如果通信文档中换一种说法(大端模式、小端模式)的话,可能就需要思考一下,或者说需要理解一下才行。

  例如tcp/ip协议中,对于ip地址和端口号,要求的必须是网络字节序,也就是大端字节序模式。那我们到底是先发送高字节还是先发送低字节呢?其实在其他的232/485/can/蓝牙/等等通信方式中,也有同样的概念。

  那对于多字节通信中,人为定义了(注意,这里的定义的概念和多字节存储中的是同等级的,你可以理解为他们两个没有关系):

  • 大端序模式:先发送高字节,后发送低字节。
  • 小端序模式:先发送低字节,后发送高字节。

  既然上述概念是大多数人为约定的,那么可能就有这样那样的误解。所以,一般通信文档上说明了大端模式、还是小端模式外,还需要标注MSB or LSB first,或者直接注明先发高或者是低字节,避免双方出现误解。

  当然,有没有方法可以记忆多字节通信中,这种大多数人定义的概念呢?下文提供了一种我的记忆方案吧。

	//x86-64 ubuntu 18.04
uint16_t ttt = 0xAABB;
uint16_t ttt_hton = htons(ttt);//把ttt转换为网络字节序,大端模式
uint8_t array[4] = {0xAA, 0xBB, 0xCC, 0xDD};

  在c&&c++数组中,数组名字是指向的这个数组的低地址。假如我要按地址自增方向发送这个数组的数据,如果数组中先存放高字节(也就是说低地址存放高字节,或者说先发送高字节),那么这种通信方案中,字节序为大端模式。小端模式同理可得。

  但是,这仅仅是一种记忆方案。而且这是一种通用的约定,具体还是要看通信文档的定义,例如tcp/ip中的ip和端口号字节序定义就是MSB first。如果某一天,哪个人可能直接定义大端模式就是先发送低字节,也是有可能的。

后记


  总结

  大小端对于存储和通信来说,我个人认为有着不同的含义。虽然可以通过一些方法联系起来记忆。

  但是我认为,以上的内容都不是重点,是一些概念的东西,重点的是,你要明白为啥会出现这个大小端的问题?什么是字节序?为什么会有字节序这个概念就行了?

参考文献


打赏、订阅、收藏、丢香蕉、硬币,请关注公众号(攻城狮的搬砖之路)

PS: 请尊重原创,不喜勿喷。

PS: 要转载请注明出处,本人版权所有。

PS: 有问题请留言,看到后我会第一时间回复。

大端(big endian) 小端(little endian) --- 在多字节存储 和 多字节通信中的含义(我还是太年轻了)的更多相关文章

  1. 大端(big endian)和小端(little endian)

    http://www.cnblogs.com/Romi/archive/2012/01/10/2318551.html 当前的存储器,多以byte为访问的最小单元,当一个逻辑上的地址必须分割为物理上的 ...

  2. 大端模式 VS 小端模式

    简单点说,就是字节的存储顺序,如果数据都是单字节的,那怎么存储无所谓了,但是对于多字节数据,比如int,double等,就要考虑存储的顺序了.注意字节序是硬件层面的东西,对于软件来说通常是透明的.再说 ...

  3. intel 系列的PC机处理器是大端的还是小端的?

    intel 系列的PC机处理器是大端的还是小端的?由于要安装oracle,需要知道是大端机器还是小端的,你好,现在流行的PC,是微型处理器,也就是所谓的小端处理器. 大端处理器是由若干个微型处理器有机 ...

  4. 大端模式、小端模式和C#反转

    A.C#大端模式和小端模式. 小端(little-endian)模式:低地址上存放低字节,高地址上存放高字节. 如0x11223344→ byte[] numBytes = new byte[]{ 0 ...

  5. 大端BigEndian、小端LittleEndian与字符集编码

    BigEndian(大端):低字节在高内存地址 LittleEndian(小端):低字节在低内存地址 也就是看低字节在高内存地址还是低内存地址,也就是看低字节在前还是高字节在前,低字节在前自然是小端, ...

  6. C/C++ 工具函数 —— 大端模式和小端模式的互换

    小端模式:小在小,大在大:大端模式:小在大,大在小: uint32_t swap_endian(uint32_t val) { val = ((val << 8) & 0xFF00 ...

  7. 【C/C++开发】内存对齐(内存中的数据对齐)、大端模式及小端模式

    数据对齐,是指数据所在的内存地址必须是该数据长度的整数倍.DWORD数据的内存起始地址能被4除尽,WORD数据的内存起始地址能被2除尽.X86 CPU能直接访问对齐的数据,当它试图访问一个未对齐的数据 ...

  8. C# 中大端序与小端序

    C# 中大端序与小端序 static void Main(string[] args) { uint value = 0x12345678; Console.WriteLine("原始字节序 ...

  9. 大端(Big Endian)与小端(Little Endian)

    1. 你从哪里来?端模式(Endian)的这个词出自Jonathan Swift书写的<格列佛游记>.这本书根据将鸡蛋敲开的方法不同将所有的人分为两类,从圆头开始将鸡蛋敲开的人被归为Big ...

  10. 大端字节序&小端字节序(网络字节序&主机字节序)

    大端字节序:整数的高位字节存储在内存的低地址处,低字节存储在内存的高地址处. 小端字节序:整数的高位字节存储在内存的高地址处,低字节存储在内存的低地址处. 一般pc大多采用小端字节序,也称为主机字节序 ...

随机推荐

  1. 7.函数的使用--《Python编程:从入门到实践》

    7.1 python 中函数的定义   python 中函数使用 def 定义: def greet_user(): 7.2 传参的传递   普通实参的传毒,可以与 C++ 相同,即按顺序传递. 7. ...

  2. PostgreSQL-常用命令汇总

    1.连接到 PostgreSQL 数据库: psql -h 主机名/服务器IP -p 端口号 -U 用户名 -d 数据库名 注意:(1)在服务器上本地登录时,可以使用主机名或者本机IP地址进行登录,但 ...

  3. select * 的使用说明

    一. SELECT * 的含义 select * 语句是从指定的表中按照顺序返回所有列. 二. SELECT * 的优缺点 1  优点 在实际开发过程中,大家习惯性地使用select *  from  ...

  4. JS Leetcode 374. 猜数字大小 题解分析

    壹 ❀ 引 本题来自LeetCode 374. 猜数字大小,题目难度简单,与昨天的题目一样,也是一道标准二分法的题目,不知道是不是端午节的缘故,这两天的题目都比较简单,题目描述如下: 猜数字游戏的规则 ...

  5. nginx 剔除请求参数 $args 变量中任意指定参数之万金油

    剔除任意指定参数配置 只需要修改需要剔除的参数key(如:redirectUrl) #剔除$args中的redirectUrl 参数 server { listen 80; server_name w ...

  6. Spring Boot学生信息管理系统项目实战-1.项目介绍

    1.获取源码 需要源码的朋友,请捐赠任意金额后留下邮箱发送:) 2.项目背景 刚开始自己帮教师朋友写的,核心是学生信息的导入导出功能.后来又扩展了几个模块. 水平一般能力有限,觉着有用的朋友可以拿去自 ...

  7. StretchDIBits在一些图像尺寸下失败

    StretchDIBits用来打印图像,但是由于某种未知的原因,当图像达到特定尺寸时,它会失败. 图像数据从其他一些图像源以24位BGR格式加载到无符号int数组中.它可以在某些大小下工作,但根本无法 ...

  8. win32-UpdateLayeredWindow

    创建半透明的窗口,以及在窗口上绘制不透明的文本 方法: 创建Bitmap具有PixelFormat32bppPARGB像素格式的GDI + 对象. 创建一个Graphics对象以绘制该Bitmap对象 ...

  9. AirtestProject浅尝辄止

    AirtestProject是什么 AirtestProject是由网易游戏推出的UI自动化测试解决方案,主要包含3部分内容: 1.Airtest框架:跨平台的,基于图像识别的UI自动化测试框架,支持 ...

  10. 一个自定义可扩展的检测变量的函数typeofIt();

    自定义方法typeofIt()是用来判断传入的变量或属性是什么类型的; 1.如果是基础类型变量则返回代表基础变量类型小写格式的字符串及一些简易说明; 2.如果是对象类型变量则返回结尾带有"O ...