大端(big endian) 小端(little endian) --- 在多字节存储 和 多字节通信中的含义(我还是太年轻了)
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) --- 在多字节存储 和 多字节通信中的含义(我还是太年轻了)的更多相关文章
- 大端(big endian)和小端(little endian)
http://www.cnblogs.com/Romi/archive/2012/01/10/2318551.html 当前的存储器,多以byte为访问的最小单元,当一个逻辑上的地址必须分割为物理上的 ...
- 大端模式 VS 小端模式
简单点说,就是字节的存储顺序,如果数据都是单字节的,那怎么存储无所谓了,但是对于多字节数据,比如int,double等,就要考虑存储的顺序了.注意字节序是硬件层面的东西,对于软件来说通常是透明的.再说 ...
- intel 系列的PC机处理器是大端的还是小端的?
intel 系列的PC机处理器是大端的还是小端的?由于要安装oracle,需要知道是大端机器还是小端的,你好,现在流行的PC,是微型处理器,也就是所谓的小端处理器. 大端处理器是由若干个微型处理器有机 ...
- 大端模式、小端模式和C#反转
A.C#大端模式和小端模式. 小端(little-endian)模式:低地址上存放低字节,高地址上存放高字节. 如0x11223344→ byte[] numBytes = new byte[]{ 0 ...
- 大端BigEndian、小端LittleEndian与字符集编码
BigEndian(大端):低字节在高内存地址 LittleEndian(小端):低字节在低内存地址 也就是看低字节在高内存地址还是低内存地址,也就是看低字节在前还是高字节在前,低字节在前自然是小端, ...
- C/C++ 工具函数 —— 大端模式和小端模式的互换
小端模式:小在小,大在大:大端模式:小在大,大在小: uint32_t swap_endian(uint32_t val) { val = ((val << 8) & 0xFF00 ...
- 【C/C++开发】内存对齐(内存中的数据对齐)、大端模式及小端模式
数据对齐,是指数据所在的内存地址必须是该数据长度的整数倍.DWORD数据的内存起始地址能被4除尽,WORD数据的内存起始地址能被2除尽.X86 CPU能直接访问对齐的数据,当它试图访问一个未对齐的数据 ...
- C# 中大端序与小端序
C# 中大端序与小端序 static void Main(string[] args) { uint value = 0x12345678; Console.WriteLine("原始字节序 ...
- 大端(Big Endian)与小端(Little Endian)
1. 你从哪里来?端模式(Endian)的这个词出自Jonathan Swift书写的<格列佛游记>.这本书根据将鸡蛋敲开的方法不同将所有的人分为两类,从圆头开始将鸡蛋敲开的人被归为Big ...
- 大端字节序&小端字节序(网络字节序&主机字节序)
大端字节序:整数的高位字节存储在内存的低地址处,低字节存储在内存的高地址处. 小端字节序:整数的高位字节存储在内存的高地址处,低字节存储在内存的低地址处. 一般pc大多采用小端字节序,也称为主机字节序 ...
随机推荐
- 鹏程杯子2023 pwn
主要就是修改stdin的最后几位,使他变为write,然后泄露libc,为所欲为即可. 本人是卡在不知道stdin那里可以修改. 然后使用一下jmp qword rbp这个gadget 0x400a9 ...
- dotnet-cnblog tool 测试案例
这是测试donet-cnblog工具是否能将正常的Typora图片转换为博客园格式 测试1:本地图片导入 测试2:QQ截图 测试3:url https://pics3.baidu.com/feed/9 ...
- 如何用低代码实现批量导出PDF?
前言 事情是这样的,熟悉我们的朋友都知道,我司有一个为广大开发者朋友们提供学习帮助的地方,叫做新手训练营,具体的内容就是会针对初次接触葡萄城产品和技术的用户,通过 2-3 天的集中学习,采用直播授课的 ...
- NC25879 外挂
题目链接 题目 题目描述 我的就是我的,你也是我的,记住了,狐狸! --韩信-白龙吟 对于打赌输了的小T会遭受到制裁,小s修改了数据库使他可以派出许多军队来围攻小T. 很不幸,小T与小s打赌打输了 ...
- NES/FC游戏: 勇者斗恶龙2
武器 名称 攻击力 价格 主角 王子 公主 来源 Bamboo Stick 2 - x x x Wielded by the Princess of Moonbrooke at the start o ...
- Swoole从入门到入土(3)——TCP服务器[基本配置项]
在这一节的开篇,让我们先解决上一节的"配置"话题.对于server对象,有很多配置项决定了服务端的行为,可以用set的函数进行配置的设置. 1.函数set:用于设置运行时的各项参数 ...
- eclipse安装UML插件
安装AmaterasUML AmaterasUML 是一个用于 Eclipse 的轻量级 UML 和 ER 图编辑器. 将AmaterasUML的3个jar包拷到Eclpise的plugins文件下: ...
- Java集合框架学习(十一) Hashtable详解
Hashtable介绍 1. 继承自Dictionary; 2. 线程安全: 3. 支持Iterator和Enumeration: 4. key和value都不可为null; 5. 一般用于多线程环境 ...
- golang指针和结构体
指针 指针操作 指针包括指针地址.指针类型和指针取值 &: &符号放在变量前面进行取地址操作 **:*放在变量前面根据地址进行取值 指针地址: func main() { var a ...
- C++ { } 的使用场景
{} 可以用于初始化 C++11 中的变量,就像它们用于初始化 C 中的数组和结构一样. {} 主要是为了提供语法的一致性(使用 {} 初始化将在所有上下文中都有效,而使用赋值运算符或()初始化将在特 ...