社攻联盟 - 大型多人在线游戏活动平台

社攻联盟 - 大型多人在线游戏活动平台

shape

一文读懂大小端:从原理到实践的深度剖析

  • Home
  • 公会基地
  • 一文读懂大小端:从原理到实践的深度剖析
  • 2025-12-15 22:53:25
  • admin

推荐下我之前写的C/C++ OpenGL入门专栏,如果你想学习OpenGL,欢迎订阅,也可以通过底部的阅读原文进入

最近一次的项目组会议中涉及到了大小端的讨论,而后我又在读者交流群内发了条消息,想引发大家对于这个基本概念——大小端的思考。后来读者朋友想要让我写一篇文章来讨论下大小端的问题,遂作本文。

我写文章分析问题的通常有一个固定的思路,是什么(What)、为什么(Why)、怎么做/用(How)。本文也将按照这个思路进行。

1. 什么是大小端?我们学习任何一门语言时,都需要了解支持的数据类型及其占用的字节数,在不考虑特殊平台/编译器(下同,本文均不考虑特殊平台、特殊编译器)的情况下:

char:占用1个字节;int:占用4个字节;long:占用4个字节;float:占用4个字节;double:占用8个字节;我们可以看到除char外占用超过一个字节。我们知道内存以字节为单位存储数据,那内存中是如何存储大于一个字节的数据呢。 以int类型的数据为例,已知int类型数据占用四个字节,如存在数据int a = 0x12345678,a在内存中如何存储的呢?是从高位开始排,还是从低位开始排?

从低位排或者从高位排,这是两种字节序的讨论:

大端(Big Endian):高位字节排在低地址处,低位字节排在高地址处。小端(Little Endian):低位字节排在低地址处,高位字节排在高地址处。你可以把它类比为读书的顺序:

大端更像是我们平常从左往右写字(高位在前)。小端则像是从右往左写字(低位在前)。针对于上文提到的int型数据a,其大小端的存储方式如下:

通过该表格,可以看到:大端更符合我们的阅读习惯。

2.为什么会有大小端?为什么会出现两种存储类型呢,为什么当初没能够统一呢?出现两种存储类型,不仅增加了理解负担,而且增加了使用成本。

究其原因,是因为计算机体系结构的不同,导致不同的处理器架构做出了不同的选择:

摩托罗拉(PowerPC 等) 使用的是大端序。Intel x86 系列 一直使用小端序。ARM 架构 比较灵活,很多芯片可以配置成大端或小端。既然大端是符合我们的阅读习惯的,为什么会出现小端呢?主要是为了在某些运算(如整数低位截取)时更方便——因为地址最低的那一位刚好就是最低有效字节。 所以说:大端方便人类阅读,小端方便机器运算。

两种字节序具有其各自的优势,但是两种字节序的存在,也导致了新的问题——当字节序不一致时,解析数据将会出错。

3. 怎么做为了避免数据解析出错,我们应该做好两步:

判断当前平台的大小端和待解析数据的大小端是否一致;如果不一致,则进行转换;所以,首要任务是判断当前平台是大端还是小端?

3.1 大小端判断结合大小端的定义——大端的高位字节在低地址处,小端的低位字节在低地址处,我们可以通过一个简单的 C 语言代码来判断当前平台的大小端:

代码语言:javascript复制int IsLittleEndian() {

int a = 1;

return *(char*)&a == 1; // 如果最低地址存的是 1,就是小端

}

3.2 数据转换如果当前平台的大小端和数据的大小端不一致,则需要进行转换。转换的方式有很多:

自己写转换函数自己书写转换方法也很简单,需要配合移位操作和按位与操作。如下是一个简单的转换函数:

代码语言:javascript复制uint32_t SwapEndian(uint32_t val) {

return ((val >> 24) & 0x000000FF) |

((val >> 8) & 0x0000FF00) |

((val << 8) & 0x00FF0000) |

((val << 24) & 0xFF000000);

}

借助成熟的序列化库当前存在很多成熟的序列化库,如protobuf、flatbuffers等,它们都提供了跨平台、跨语言的数据序列化和反序列化功能,并且自动处理了大小端的问题。可以自行查找对应的库,本文不再赘述。

4. 总结其实大小端是一个老生常谈但又非常基础的问题,本文从是什么、为什么、怎么做三个方面进行了分析,希望对你有所帮助。

Previous Post
秒拍视频如何添加音乐?音乐怎么选择?2023-07-17 18:03:403960浏览

Copyright © 2088 社攻联盟 - 大型多人在线游戏活动平台 All Rights Reserved.

友情链接