关于大端法和小端法

本文深入探讨了字节序(大端法与小端法)在计算机存储数据时的重要性,通过实例展示了如何根据字节序计算内存中存储的数据值,并提供了判断机器字节序的函数实现。

 

typedef union {
	int  n;
	char p[sizeof(int)];
} union_t;

union_t ut;
memset(&ut,0, sizeof(ut));
ut.p[0] = 13;
printf("%d\n", ut.n);
 

输出结果是什么?

 

 

一般来说,大部分用户的操作系统(如windows, FreeBsd,Linux)是Little Endian

的。少部分,如MAC OS ,是Big Endian 的。

 

所谓MSB (Most Significant Byte)就是,一个数字中,最重要的那位,

比如,12004,中文读作,一万两千零四,那最高位的1,就表示了一万,此处就称作MSB,最有意义的位.

而LSB (Least Significant Byte)与MSB相反,个位数4就可以称为LSB,

在草稿纸上演算的时候,我们习惯左边写数的MSB,右边写数的LSB。

 

使用Little Endian方式存储数据时,数据的MSB存放在高地址,LSB存放在低地址

比如 0x11223344 ,它在内存中存储为

44 33 22 11 

低地址-->高地址

使用Big Endian方式存储数据时,数据的MSB存放在低地址,LSB存放在高地址

比如 0x11223344 ,它在内存中存储为

11 22 33 44

低地址-->高地址

 

值得注意的是,大端法和小端法讨论的都是字节与字节之间的顺序,至于一个字节内的8个比特,无论大端法还是

小端法,顺序都是一样的,即右边存储低位,左边存储高位。再看一个例子:

 

已知内存中从低地址到高地址存储的4个字节依次是:

11 22 33 44

求这个数是多少?

关键是找出哪头是MSB,哪头是LSB

 

如果该机器是Little Endian,

则低地址存放的是LSB,所以11是LSB,高地址是MSB,所以44是MSB

所以这个数等于

0x44332211

 

如果该机器是Big endian,

则低地址存放的是MSB,所以11是MSB,高地址是LSB,所以44是LSB

0x11223344

 

这个笔试题的意思是,已知内存中从低地址到高地址存储的4个字节是

0D 00 00 00

使用小端法表示,这个数等于0x0000000D,即13。

 

再引申一个问题,试写一个函数判断机器是否为Big Endian。

思想是取一个short数0x1122的第1个字节,若这个字节等于0x11,则是大端法

 

int is_big_endian()
{
	unsigned short test = 0x1122;
	if(*( (unsigned char*) &test ) == 0x11)
		return 1;
	else
		return 0;
}
<think>我们根据用户要求,结合站内引用资料,整理大端小端序的相关知识。 引用资料中已经提供了比较详细的解释,我们将这些信息进行整合,并用清晰的结构呈现。 注意:用户要求获取相关知识,因此我们需要全面但简洁地介绍概念、区别、存储方式、应用场景等。 根据引用[2][3][4]: 小端序(Little-Endian):低位字节存入低地址,高位字节存入高地址。 大端序(Big-Endian):高位字节存入低地址,低位字节存入高地址。 举例(引用[4]):变量0x11223344 大端模式存储(假设地址从0x0001到0x0004): 0x0001 (低地址) : 0x11 0x0002 : 0x22 0x0003 : 0x33 0x0004 (高地址) : 0x44 小端模式存储: 0x0001 (低地址) : 0x44 0x0002 : 0x33 0x0003 : 0x22 0x0004 (高地址) : 0x11 为什么要有字节序(引用[2][5])? 计算机内部处理(CPU处理)通常使用小端序,因为计算机从低位开始计算,先处理低位字节效率更高。 但是,人类习惯读写大端序(因为书写习惯是从左到右,左边是高位,右边是低位)。 在网络传输文件存储中,为了统一,通常使用大端序(网络字节序)。 引用[1]还提到了在Linux内核中I2C通信的寄存器地址使用了大小端序的宏区分(如CCI_16是大端序,CCI_16_LE是小端序),这指的是寄存器值在buffer内的存放方式。 此外,引用[4]提供了一个记忆口诀:“自大的人眼高手低”: - 自大:代表大端序 - 眼高:代表高地址 - 手低:代表低字节 即大端序中,高地址存放的是低字节(低字节在高地址)。那么反过来,小端序就是高地址存放高字节。 但注意:这个口诀描述的是大端序的特点,我们可以这样理解: 大端序:高地址存放低字节(低字节放在高地址) 小端序:高地址存放高字节(高字节放在高地址) 不过,我们也可以换一种方式记忆(更常见的): 大端序:高字节在前(低地址放高字节),符合人类阅读习惯。 小端序:低字节在前(低地址放低字节),符合计算机处理习惯。 应用场景: 1. 网络传输:使用大端序(网络字节序) 2. 文件存储:通常使用大端序(如PNG图像格式等) 3. 计算机内部处理:通常是小端序(如x86架构) 判断当前系统是大端序还是小端序的方(代码示例): 我们可以通过将多字节整数(如int)的地址强制转换为单字节(如char)的指针,然后检查低地址处存放的是整数的高位还是低位。 下面我们用C语言代码示例: </think>### 大端小端序详解 #### **1. 基本概念** - **大端序(Big-endian)** 高位字节存放在低地址,低位字节存放在高地址(符合人类阅读习惯)。 示例:数值 `0x11223344` 在内存中的存储(地址从左到右递增): `低地址 → 0x11 0x22 0x33 0x44 ← 高地址` [^3][^4] - **小端序(Little-endian)** 低位字节存放在低地址,高位字节存放在高地址(符合计算机处理逻辑)。 示例:数值 `0x11223344` 的存储: `低地址 → 0x44 0x33 0x22 0x11 ← 高地址` [^2][^3] #### **2. 核心区别** | 特征 | 大端序 | 小端序 | |--------------|----------------------------|----------------------------| | 字节存放顺序 | 高字节→低地址,低字节→高地址 | 低字节→低地址,高字节→高地址 | | 人类可读性 | 直观(如 `0x1122` 存储为 `11 22`) | 反序(存储为 `22 11`) | | 硬件处理效率 | 较低 | 较高(CPU从低位开始计算) [^5] | #### **3. 设计原因** - **小端序优势**: CPU处理数据时从低位开始计算(如加进位),低字节在低地址可直接读取,效率更高 [^5]。 - **大端序优势**: 网络传输(如TCP/IP协议)文件存储(如BMP图像)采用大端序作为标准(网络字节序),确保跨平台一致性 [^1][^5]。 #### **4. 应用场景** - **常用大端序**: 网络协议(IPv4/IPv6)、Java虚拟机、PowerPC处理器、PNG图像格式。 - **常用小端序**: x86/x64处理器、ARM架构(默认小端)、Linux内核驱动(如I2C的CCI_16_LE寄存器)[^1]。 #### **5. 快速记忆** - **口诀**: > "**自大**的人**眼高**(高地址)**手低**(低字节)" → 大端序中高地址存低字节 [^4]。 反之,小端序则是高地址存高字节。 #### **6. 代码检测示例(C语言)** ```c #include <stdio.h> int main() { int num = 0x11223344; char *p = (char*)# // 指向低地址 if (*p == 0x11) printf("Big-endian\n"); // 低地址存高字节 else if (*p == 0x44) printf("Little-endian\n"); // 低地址存低字节 return 0; } ``` #### **7. 典型问题分析** - **跨平台数据传输**: 网络通信时需用 `htonl()`(主机到网络序)将小端主机数据转为大端序,接收用 `ntohl()` 转回 [^5]。 - **寄存器配置**(如I2C): Linux内核用 `CCI_16` 标识大端序寄存器,`CCI_16_LE` 标识小端序寄存器 [^1]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值