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. 探索C语言的数据类型:解密编程世界的核心秘密

    欢迎大家来到贝蒂大讲堂 养成好习惯,先赞后看哦~ 所属专栏:C语言学习 贝蒂的主页:Betty's blog 1. 常量与变量 1.1 常量 (1) 常量的概念 常量顾名思义就是无法改变的量,比如一周 ...

  2. BZOJ3364 Distance Queries 距离咨询 题解

    原题 简化题意:有一棵 \(n\) 个点的树, \(q\) 组询问,每次询问回答两点间的距离. 令 \(dis[i][j]\) 表示 \(i\) 到 \(j\) 的距离,根节点为 \(rt\) ,则有 ...

  3. JS leetcode 实现strStr()函数 题解分析

    壹 ❀ 引 前几天心情比较浮躁,烦心事太多,偷懒了3天,还是继续刷leetcode.那么今天做的题目为实现 strStr() 函数.,原题如下: 给定一个 haystack 字符串和一个 needle ...

  4. Python三次样条插值与MATLAB三次样条插值简单案例

    1 三次样条插值 早期工程师制图时,把富有弹性的细长木条(所谓样条)用压铁固定在样点上,在其他地方让它自由弯曲,然后沿木条画下曲线,成为样条曲线. 设函数S(x)∈C2[a,b] ,且在每个小区间[x ...

  5. VueRouter导航守卫

    VueRouter导航守卫 vue-router提供的导航守卫主要用来通过跳转或取消的方式守卫导航,简单来说导航守卫就是路由跳转过程中的一些钩子函数,路由跳转是一个大的过程,这个大的过程分为跳转前中后 ...

  6. RedHat5 安装中文输入法

    为了学习linux命令,虚拟机里搞了个RedHat 5.4 .下面是安装中文输入法过程: 1.下载并安装小企鹅输入法 fcitx-3.0.0-1.i386.rpm 2.安装后执行以下命令: # cd ...

  7. 解决:EXP-00003: 未找到段 (0,0) 的存储定义报错

    问题说明 DB服务器oracle版本:11.2.0.4.0 最近在客户端用exp命令导出部分表时报错,如题.搜索了一下,找到以下解决方案: 问题原因 Oracle 11g 有一个参数deferred_ ...

  8. iptables临时控制某ip访问权限

    iptables -A INPUT -p tcp -s {src_ip} --dport 80 -j ACCEPT iptables -A INPUT -p tcp -s {src_ip} --dpo ...

  9. 以二进制文件安装K8S之创建CA根证书

    为etcd和Kubernetes服务启用基于CA认证的安全机制,需要CA证书进行配置. 如果组织能够提供统一的CA认证中心,则直接使用组织颁发的CA证书即可.如果没有统一的CA认证中心,则可以通过颁发 ...

  10. 使用Java线程同步工具类CyclicBarrier

    如何使用 java.util.concurrent.CyclicBarrier是Java并发并发编程中的线程同步工具类,基于java.util.concurrent.locks.ReentrantLo ...