大端格式、小段格式,以及数据在内存中的存储方式

本文详细解释了大端和小端存储模式的概念及其在不同架构中的应用,通过具体实例展示了这两种模式如何影响数据在内存中的排列,并探讨了它们各自的优缺点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

大端格式、小格式、数据在内存中的存储方式



内存中的地址.左→右,地址降低,下→上,地址升高。一个格子是一个字节,一个字节是8位。
int a = 0x01020304

若为大端格式(arm默认是小段格式):地地址存放高位
 内存格式
0x40010x40020x40030x4004
01020304
    


小端格式:x86、windows:低地址存放底位

 内存格式
0x40010x40020x40030x4004
04030201
    


测试函数,我的linux是小端格式,下面请看程序

#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <string.h>

typedef struct led_reports_st {
     char ch; 
     int it; 
     char string[3]; 
     uint32_t serial_no; 
}node;

node Node = {0x01, 0x01020304, "a", 32};
int main ()
{
int i;
char *p_char;
p_char = (char *)&Node;
for(i=0; i < sizeof(Node); i++)
{
printf("a[%d]:%d\n", i, p_char[i]);
}
printf("sizeof(Node):%d\n", sizeof(Node));
printf("sizeof(uint32_t):%d\n", sizeof(uint32_t));
return 1;
}

输出结果是:
a[0]:1
a[1]:0
a[2]:0
a[3]:0
a[4]:4
a[5]:3
a[6]:2
a[7]:1
a[8]:97
a[9]:0
a[10]:0
a[11]:0
a[12]:32
a[13]:0
a[14]:0
a[15]:0
sizeof(Node):16
sizeof(uint32_t):4

可以看到a[4]-a[7]中的数据是04、03、02、01。所以是小端格式。


另外,该实例程序还展示了char指针的一种用途,将结构体转换成char指针,这样如果清楚struct的结构体和内存对齐格式,就可以直接使用数组读取结构体中的指定内容了。
指针是一种非常灵活的东西,需要多理解。



详解大端模式和小端模式

一、大端模式和小端模式的起源

        关于大端小端名词的由来,有一个有趣的故事,来自于Jonathan Swift的《格利佛游记》:Lilliput和Blefuscu这两个强国在过去的36个月中一直在苦战。战争的原因:大家都知道,吃鸡蛋的时候,原始的方法是打破鸡蛋较大的一端,可以那时的皇帝的祖父由于小时侯吃鸡蛋,按这种方法把手指弄破了,因此他的父亲,就下令,命令所有的子民吃鸡蛋的时候,必须先打破鸡蛋较小的一端,违令者重罚。然后老百姓对此法令极为反感,期间发生了多次叛乱,其中一个皇帝因此送命,另一个丢了王位,产生叛乱的原因就是另一个国家Blefuscu的国王大臣煽动起来的,叛乱平息后,就逃到这个帝国避难。据估计,先后几次有11000余人情愿死也不肯去打破鸡蛋较小的端吃鸡蛋。这个其实讽刺当时英国和法国之间持续的冲突。Danny Cohen一位网络协议的开创者,第一次使用这两个术语指代字节顺序,后来就被大家广泛接受。
 

二、什么是大端和小端

        Big-Endian和Little-Endian的定义如下:
1) Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。
2) Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。
举一个例子,比如数字0x12 34 56 78在内存中的表示形式为:

1)大端模式:

低地址 -----------------> 高地址
0x12  |  0x34  |  0x56  |  0x78

2)小端模式:

低地址 ------------------> 高地址
0x78  |  0x56  |  0x34  |  0x12

可见,大端模式和字符串的存储模式类似。

3)下面是两个具体例子:

16bit宽的数0x1234在Little-endian模式(以及Big-endian模式)CPU内存中的存放方式(假设从地址0x4000开始存放)为:

内存地址 小端模式存放内容 大端模式存放内容
0x4000 0x34 0x12
0x4001 0x12 0x34

32bit宽的数0x12345678在Little-endian模式以及Big-endian模式)CPU内存中的存放方式(假设从地址0x4000开始存放)为:

内存地址 小端模式存放内容 大端模式存放内容
0x4000 0x78 0x12
0x4001 0x56 0x34
0x4002 0x34 0x56
0x4003 0x12 0x78

 4)大端小端没有谁优谁劣,各自优势便是对方劣势:

小端模式 :强制转换数据不需要调整字节内容,1、2、4字节的存储方式一样。
大端模式 :符号位的判定固定为第一个字节,容易判断正负。

三、数组在大端小端情况下的存储:

  以unsigned int value = 0x12345678为例,分别看看在两种字节序下其存储情况,我们可以用unsigned char buf[4]来表示value:
  Big-Endian: 低地址存放高位,如下:
高地址
        ---------------
        buf[3] (0x78) -- 低位
        buf[2] (0x56)
        buf[1] (0x34)
        buf[0] (0x12) -- 高位
        ---------------
        低地址
Little-Endian: 低地址存放低位,如下:
高地址
        ---------------
        buf[3] (0x12) -- 高位
        buf[2] (0x34)
        buf[1] (0x56)
        buf[0] (0x78) -- 低位
        --------------
低地址


四、为什么会有大小端模式之分呢?

      这是因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为8bit。但是在C语言中除了8bit的char之外,还有16bit的short型,32bit的long型(要看具体的编译器),另外,对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如果将多个字节安排的问题。因此就导致了大端存储模式和小端存储模式。例如一个16bit的short型x,在内存中的地址为0x0010,x的值为0x1122,那么0x11为高字节,0x22为低字节。对于大端模式,就将0x11放在低地址中,即0x0010中,0x22放在高地址中,即0x0011中。小端模式,刚好相反。我们常用的X86结构是小端模式,而KEIL C51则为大端模式。很多的ARM,DSP都为小端模式。有些ARM处理器还可以由硬件来选择是大端模式还是小端模式。


<think>首先,用户的问题是关于大端和小端的概念及其区别。用户说:"我想理解大端和小端的概念及其区别 请问大端和小端的区别以及各自定义"。我需要根据系统级指令来回答。 系统级指令: 1. 所有行内数学表达式必须使用 $...$ 格式。 2. 独立公式必须使用 $$...$$ 格式并单独成段。 3. LaTeX语法正确。 4. 使用中文回答。 5. 生成相关问题。 6. 回答中引用的段落末尾自然地添加引用标识,例如 [^1]。 用户可见层: - 回答结构清晰,帮助用户逐步解决问题。 - 尽量保证回答真实可靠。 参考站内引用: - 引用 [1], [2], [3] 提供了大端和小端的定义和区别。我需要整合这些信息。 关键点来自引用: - 引用 [1]: 大端模式:高位字节在低地址端,低位字节在高地址端。小端模式相反。 - 引用 [2]: 大端:最高字节在最低内存地址;小端:最低字节在最低内存地址。 - 引用 [3]: 解释了为什么存在大端和小端,因为处理器如何处理多字节数据。X86是小端,ARM和DSP可能小端,C51是大端。 我的回答应该结构清晰: 1. 定义大端和小端。 2. 解释区别。 3. 举例说明。 4. 讨论为什么重要。 5. 生成相关问题。 使用中文回答。 行内数学表达式:如果有数学内容,比如地址或值,但这里主要是概念性的,可能不需要太多数学。但如果有数字,比如地址0x0010,值0x1122,我应该用行内格式,如 $0x0010$。 例如,引用中提到 "数值 0x1234",我应该写为 $0x1234$。 独立公式:可能没有复杂的公式,但如果有,比如描述地址映射,我可以使用。 现在,生成相关问题:在回答末尾,添加相关问题部分。 引用标识:在回答中引用段落时,在末尾添加 [^1], [^2], [^3]。但系统指令说 "回答中引用的段落末尾自然地添加引用标识",意思是当我在回答中引用站内内容时,添加标识。我应该基于提供的引用进行总结,而不是直接复制。 结构回答: - 开头简要介绍。 - 定义大端和小端。 - 解释区别。 - 举例。 - 为什么存在。 - 如何识别。 - 相关问题。 逐步解决问题: 1. 什么是大端模式? 2. 什么是小端模式? 3. 它们的主要区别是什么? 4. 实际例子。 5. 应用和重要性。 最后,添加相关问题。 确保回答真实可靠:基于计算机科学常识。</think>### 大端和小端的概念及其区别 大端(Big-Endian)和小端(Little-Endian)是计算机系统中用于描述多字节数据(如整数、浮点数)在内存中存储顺序的两种模式。这些模式主要影响处理器如何读取和写入数据,尤其在处理多字节数据类型(如16位short型、32位long型)时至关重要。以下我将逐步解释它们的定义、区别、原因和实际应用。 #### 1. **大端模式和小端的定义** - **大端模式 (Big-Endian)**:在这种模式下,数据的高位字节(即数值的最高有效字节)存储在内存的低地址端,而低位字节(即数值的最低有效字节)存储在内存的高地址端。简单来说,数据按照从高位到低位的顺序存储,地址递增的方向对应字节从高到低[^1]。 - 例如,对于16位数值 $0x1234$(其中 $0x12$ 是高位字节,$0x34$ 是低位字节),在大端模式中,内存地址从低到高依次存储:地址 $0x0010$ 存 $0x12$,地址 $0x0011$ 存 $0x34$[^2][^3]。 - **小端模式 (Little-Endian)**:在这种模式下,数据的低位字节存储在内存的低地址端,而高位字节存储在内存的高地址端。数据按照从低位到高位的顺序存储,地址递增的方向对应字节从低到高[^1][^2]。 - 例如,同样对于 $0x1234$,在小端模式中,内存地址从低到高依次存储:地址 $0x0010$ 存 $0x34$,地址 $0x0011$ 存 $0x12$[^3]。 #### 2. **大端和小端的主要区别** - **存储顺序**:大端模式将高位字节优先放在低地址,小端模式将低位字节优先放在低地址。这是核心区别,直接影响数据的解析方式。 - 数学表示:假设一个32位整数 $x = 0x12345678$,在内存地址起始于 $0x0000$: - 大端模式:地址 $0x0000$ 存 $0x12$(最高字节),$0x0001$ 存 $0x34$,$0x0002$ 存 $0x56$,$0x0003$ 存 $0x78$(最低字节)[^1][^2]。 - 小端模式:地址 $0x0000$ 存 $0x78$(最低字节),$0x0001$ 存 $0x56$,$0x0002$ 存 $0x34$,$0x0003$ 存 $0x12$(最高字节)[^2][^3]。 - **地址与字节关系**:在大端模式中,内存地址增加的方向对应数据从高位到低位;在小端模式中,地址增加的方向对应数据从低位到高位[^1][^2]。 - **性能影响**:没有绝对的优劣,但小端模式在算术运算中更高效,因为低字节优先处理;大端模式在网络传输(如TCP/IP协议)中更常见,因为它与人类阅读顺序一致[^3]。 #### 3. **为什么存在大端和小端模式?** - 计算机系统中,数据以字节(8位)为单位存储,但数据类型如short型(16位)或long型(32位)需要多个字节。处理器设计决定了如何安排这些字节: - 如果寄存器宽度大于一个字节(如16位或32位处理器),就必须解决字节顺序问题,导致了大端和小端模式的出现[^3]。 - 例如,X86架构(如Intel处理器)默认使用小端模式,而ARM或DSP处理器通常支持小端模式,但某些系统(如KEIL C51)使用大端模式。硬件或软件可以配置选择模式[^3]。 #### 4. **如何识别机器是大端还是小端?** - 可以通过编程测试:使用C语言代码读取多字节数据(如int型)的第一个字节。 - 小端模式下,低地址字节对应数据的低位部分;大端模式下,低地址字节对应数据的高位部分。 - 示例代码: ```c #include <stdio.h> int main() { int num = 0x12345678; char *byte = (char *)# if (*byte == 0x78) { // 低地址字节是0x78(小端) printf("Little-Endian\n"); } else if (*byte == 0x12) { // 低地址字节是0x12(大端) printf("Big-Endian\n"); } return 0; } ``` - 运行此代码,如果输出 "Little-Endian",表示机器是小端模式(常见于个人电脑);如果输出 "Big-Endian",表示大端模式(常见于嵌入式系统)[^2][^3]。 #### 5. **实际应用和重要性** - **数据兼容性**:在网络通信中,大端模式(网络字节序)是标准,确保不同设备间数据解析一致;小端模式在本地存储中更高效。 - **跨平台问题**:如果程序在不同端模式的系统间移植,可能导致数据错误(如文件读写或网络传输)。因此,开发中常使用函数如 `htonl()`(主机到网络字节序转换)来处理端序问题[^3]。 - **常见场景**:互联网协议(IP地址使用大端)、文件格式(如JPEG图像可能使用大端)、处理器设计(X86小端,PowerPC可能大端)[^1][^3]。 通过以上解释,您应该对大端和小端有了清晰理解。它们本质上是字节顺序的两种约定,理解其区别有助于避免编程错误和提升系统兼容性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值