计算机的大小端存储

大小端模式主要影响多字节数据在内存中的存储顺序。大端模式下,高地址存放低位,而小端模式则相反。对于char型数据,由于只占一个字节,所以大小端无明显差异。数组和结构体的元素或成员依然按照定义顺序从低地址到高地址存储。位域在小端模式下,先定义的位域从LSB开始,大端模式则从MSB开始。可以通过特定的代码检测系统使用的是大端还是小端模式。

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

什么是大小端?

高地址,低地址是针对内存地址而言,高位,低位是针对数据类型的bit位的高低而言。

  • 大端(Big-Endian):高地址存放低位
  • 小端(Little-Endian):高地址存放高位

大小端影响了什么?

当基本数据类型占用字节数超过了1字节后,大小端决定了数据按照什么顺序存储在内存里
既然字节数超过了1个字节才有影响,那么就会一个疑问,char型数据占用字节数为1个字节,那么char型数据在大小端的模式下,没有什么不同。

大小端只针对基本数据类型

大小端只针对基本数据单元类型,那么什么是基本数据类型单元呢,char, int, float, double,那什么不是基本数据类型呢?例如:数组,结构体,联合等等。需首先找出基本数据类型,明确数据占用字节数以及高位,低位情况
明确变量地址始终指向变量的低地址
根据大小端的特性来套表格

基本数据类型

内存地址存储的最小数据大小就是字节,例如一个变量char temp的地址0x10000000,temp值为0x55,由于char类型只占用一个字节,那么temp变量就只占用0x10000000这个内存地址,不会占用其他内存地址,假如变量是个int型呢 占用的字节数可能是4字节,这时候就有了大小端存储

例1(基本数据类型):int temp = 0x12345678;
假设 temp 的地址为 0x10000000 ,按照上面的分析步骤来拆分解析

int型占用字节数为4字节,将数据按照字节为单位的高位,低位分解如下:0x12(高位),0x34,0x56 ,0x78 (低位)
由1点可知,基本数据类型占用内存为4字节,所以内存地址范围为 0x10000000~ 0x10000003
根据大小端的特性来套表格如下

大端模式
内存地址	内存值	步骤
0x10000000	0x12	4.依次取值
0x10000001	0x34	3.依次取值
0x10000002	0x56	2.依次取值
0x10000003	0x78	1.高地址存放低位

小端模式
内存地址	内存值	步骤
0x10000000	0x78	4.依次取值
0x10000001	0x56	3.依次取值
0x10000002	0x34	2.依次取值
0x10000003	0x12	1.高地址存放高位

数组

  • 数组的元素布局顺序是固定的,从低地址到高地址。
例2(数组):short int temp[2] = {0x1234,0x5678};
假设 temp 的地址为 0x10000000 ,按照上面的分析步骤来拆分解析

short int型占用字节数为2字节,将数据按照字节为单位的高位,低位分解如下:0x12(高位),0x34(低位),0x56 (高位),0x78 (低位)
由1点可知,基本数据类型占用内存为2字节,但是由两个元素,所以内存地址范围为 0x10000000~ 0x10000003
根据大小端的特性来套表格如下
大端模式
内存地址	内存值	步骤
0x10000000	0x12	2.依次取值
0x10000001	0x34	1.高地址存放低位
0x10000002	0x56	4.依次取值
0x10000003	0x78	3.高地址存放低位
小端模式
内存地址	内存值	步骤
0x10000000	0x34	2.依次取值
0x10000001	0x12	1.高地址存放高位
0x10000002	0x78	4.依次取值
0x10000003	0x56	3.高地址存放高位

结构体

  • 结构体的成员布局顺序也是固定的,按定义的顺序从低地址到高地址。
//C code: get CPU big endian or small endian
#include <stdio.h>
 
union TEST{
	unsigned char aa[4];
	unsigned int  bb;
};
 
int main()
{
	union TEST test;
 
	test.aa[0] = 0x01;
	test.aa[1] = 0x02;
	test.aa[2] = 0x03;
	test.aa[3] = 0x04;
 
	if (test.bb == 0x01020304)
		printf("it's big endiam!\r\n");
	else if (test.bb == 0x04030201)
		printf("it's small endiam!\r\n");
	else
		printf("unknow endiam system! 0x1234 VS 0x%x\r\n", test.bb);
 
	return 0;
}
  • 联合体和结构体的成员变量的内存都是按照成员变量顺序从低地址到高地址分布。可以利用联合体的这些特性来检测系统使大端模式还是小端模式。
BOOL IsBigEndian()    
{    
    union NUM    
    {    
        int a;    
        char b;    
    }num;    
    num.a = 0x1234;    
    if( num.b == 0x12 )    
    {    
        return TRUE;    
    }    
    return FALSE;    
}  

位域

  • 小端模式,先定义的位域存储在低地址低位,后定义的位域存储在高地址中高位

  • 大端模式,先定义的位域存储在高地址中高位,后定义的位域存储在低地址低位中

  • 存在位域的情况下,小端模式下先定义的位域从LSB(最低有效位)开始,大端模式下先定义的位域从MSB(最高有效位)开始,先定义的位域因大小端情况会表示最高位或者最低位。

例3(位域结构体):

struct {
    int b1:1; 
    int b2:2; 
    int b3:3; 
    int b4:4; 
    char b5:5;
}
temp = {.b1=1, .b2=2, .b3=3, .b4=4, .b5=5 };

假设 temp 的地址为 0x10000000 ,按照上面的分析步骤来拆分解析
int型占用字节数为4字节,char型占用字节数为1字节
基本数据类型占用内存为4字节+1字节,所以内存地址范围为 0x10000000~ 0x10000004

大端下位域分布

首先分析位域情况

  • 大端下temp的int值位域分布如下 int值为0xCD000000
bit位	31	30	29	28	27	26	25	24	23	22	21	20	19	18	17	16	15	14	13	12	11	10	9	8	7	6	5	4	3	2	1	0
        b1	b2	b2	b3	b3	b3	b4	b4	b4	b4																
bit值	1	1	0	0	1	1	0	1	0	0	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-

大端下temp的char值位域分布如下 char值为0x28

bit位	7	6	5	4	3	2	1	0
        b5	b5	b5	b5	b5			
bit值	0	0	1	0	1	-	-	-

大端模式下将数据按照字节为单位的高位,低位分解如下:0xCD(高位),0x00,0x00,0x00(低位),0x28(字节)

内存地址	内存值	步骤
0x10000000	0xCD	4.依次取值
0x10000001	0x00	3.依次取值
0x10000002	0x00	2.依次取值
0x10000003	0x00	1.高地址存放低位

0x10000004	0x28	5.高地址存放低位
小端下位域分布
  • 小端下temp的int值位域分布如下 int值为0x0000011D
bit位	31	30	29	28	27	26	25	24	23	22	21	20	19	18	17	16	15	14	13	12	11	10	9	8	7	6	5	4	3	2	1	0
                                                                                                b4	b4	b4	b4	b3	b3	b3	b2	b2	b1
bit值	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	0	1	0	0	0	1	1	1	0	1

小端下temp的char值位域分布如下 char值为0x05

bit位	7	6	5	4	3	2	1	0
                    b5	b5	b5	b5	b5
bit值	-	-	-	0	0	1	0	1

小端模式下将数据按照字节为单位的高位,低位分解如下:0x00(高位),0x00,0x01,0x1D(低位),0x05(字节)

小端模式

内存地址	内存值	步骤
0x10000000	0x1D	4.依次取值
0x10000001	0x01	3.依次取值
0x10000002	0x00	2.依次取值
0x10000003	0x00	1.高地址存放高位

0x10000004	0x05	5.高地址存放高位

根据大小端不一样所需要定义的位域结构体也不一样

bit位	7	6	5	4	3	2	1	0
 (reserved 3bit)    (id 2bit) 	(connect 1bit)(status 2bit)
bit值	-	-	-	-	-	-	-	-

struct {
#if __IsBigEndian__
    uint8_t reserved:3;
    uint8_t id:3;
    uint8_t connect:1;
    uint8_t status:2;
#else
    uint8_t status:2;
    uint8_t connect:1;
    uint8_t id:3;
    uint8_t reserved:3;
#endif

} data;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值