本文仅供参考学习,如有错误之处,欢迎留言指正。
理解大小端之前必须明白的三点
- 内存地址始终以字节为单位
- 大小端只针对基本数据类型
- 存在位域的情况下,小端模式下先定义的位域从LSB(最低有效位)开始,大端模式下先定义的位域从MSB(最高有效位)开始
首先解释下以上三点
第一点,内存地址存储的最小数据大小就是字节,例如一个变量char temp的地址0x10000000,temp值为0x55,由于char类型只占用一个字节,那么temp变量就只占用0x10000000这个内存地址,不会占用其他内存地址,那假如变量是个int型呢?占用的字节数可能是4字节,这个时候内存和内存值又是怎么分配的呢?这个有待后面分析。
第二点,大小端只针对基本数据单元类型,那么什么是基本数据类型单元呢,char, int, float, double,那什么不是基本数据类型呢?例如:数组,结构体,联合等等。
第三点,先定义的位域因大小端情况会表示最高位或者最低位。
大小端影响了什么?
当基本数据类型占用字节数超过了1字节后,大小端决定了数据按照什么顺序存储在内存里
既然字节数超过了1个字节才有影响,那么就会一个疑问,char型数据占用字节数为1个字节,那么char型数据在大小端的模式下,会有什么不同吗?答案是没有。
什么是大小端?
- 大端(Big-Endian):高地址存放低位
- 小端(Little-Endian):高地址存放高位
这里有几个概念:高地址,低地址,高位,低位,其中高地址,低地址是针对内存地址而言,高位,低位是针对数据类型的bit位的高低而言。
如何根据具体情况分析
分析步骤:
- 首先找出基本数据类型,明确数据占用字节数以及高位,低位情况
- 明确变量地址始终指向变量的低地址
- 根据大小端的特性来套表格
举例:
例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.高地址存放高位 |
例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 ,按照上面的分析步骤来拆分解析
- 首先分析位域情况
大端模式下,假设-
表示0,则int值为0xCD000000,char值为0x28
大端下temp的int值位域分布如下
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值位域分布如下
bit位 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
b5 | b5 | b5 | b5 | b5 | ||||
bit值 | 0 | 0 | 1 | 0 | 1 | - | - | - |
小端模式下,假设-
表示0,则int值为0x0000011D,char值为0x05
小端下temp的int值位域分布如下
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值位域分布如下
bit位 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
b5 | b5 | b5 | b5 | b5 | ||||
bit值 | - | - | - | 0 | 0 | 1 | 0 | 1 |
- int型占用字节数为4字节,char型占用字节数为1字节
- 大端模式下将数据按照字节为单位的高位,低位分解如下:0xCD(高位),0x00,0x00,0x00(低位),0x28(字节)
- 小端模式下将数据按照字节为单位的高位,低位分解如下:0x00(高位),0x00,0x01,0x1D(低位),0x05(字节)
- 由1,2点可知,基本数据类型占用内存为4字节+1字节,所以内存地址范围为 0x10000000~ 0x10000004
- 根据大小端的特性来套表格如下
大端模式
内存地址 | 内存值 | 步骤 |
---|---|---|
0x10000000 | 0xCD | 4.依次取值 |
0x10000001 | 0x00 | 3.依次取值 |
0x10000002 | 0x00 | 2.依次取值 |
0x10000003 | 0x00 | 1.高地址存放低位 |
0x10000004 | 0x28 | 5.高地址存放低位 |
小端模式
内存地址 | 内存值 | 步骤 |
---|---|---|
0x10000000 | 0x1D | 4.依次取值 |
0x10000001 | 0x01 | 3.依次取值 |
0x10000002 | 0x00 | 2.依次取值 |
0x10000003 | 0x00 | 1.高地址存放高位 |
0x10000004 | 0x05 | 5.高地址存放高位 |
实验验证环境属于大端还是小端
测试代码如下:
#include <stdio.h>int main(int argc, char *argv[])
{int temp1 = 0x12345678;short int temp2[2] = {0x1234, 0x5678};struct{int b1:1;int b2:2;int b3:3;int b4:4;int bn:22;//这里是否需要占位根据编译器而定char b5:5;char bx:3;}temp3={.b1=1, .b2=2, .b3=3, .b4=4, .bn=0, .b5=5, .bx=0};char *_p1, *_p2;int *_p3;_p1 = (char *)&temp1;if(*_p1==0x12) printf("基本数据类型测试:大端模式\n");else if(*_p1==0x78) printf("基本数据类型测试:小端模式\n");else printf("基本数据类型测试:测试错误\n");_p1 = (char *)&temp2[0];_p2 = (char *)&temp2[1];if(*_p1==0x12 && *_p2==0x56) printf("数组类型测试:大端模式\n");else if(*_p1==0x34 && *_p2==0x78) printf("数组类型测试:小端模式\n");else printf("数组类型测试:测试错误\n");_p3 = (int *)&temp3;_p1 = (char *)&temp3; _p2 = (char *)(_p3+1);printf("temp3.int=0x%08X\n", *_p3);printf("temp3.char=0x%02X\n", *_p2);if(*_p1==0xCD && *_p2==0x28) printf("位域类型测试:大端模式\n");else if(*_p1==0x1D && *_p2==0x05) printf("位域类型测试:小端模式\n");else printf("位域类型测试:测试错误\n");return 0;
}
实验结果如下:
本文链接:https://my.lmcjl.com/post/10345.html
4 评论