C语言之什么是大小端,数组大小端,位域大小端,结构体大小端

本文仅供参考学习,如有错误之处,欢迎留言指正。

理解大小端之前必须明白的三点

  1. 内存地址始终以字节为单位
  2. 大小端只针对基本数据类型
  3. 存在位域的情况下,小端模式下先定义的位域从LSB(最低有效位)开始,大端模式下先定义的位域从MSB(最高有效位)开始

首先解释下以上三点
第一点,内存地址存储的最小数据大小就是字节,例如一个变量char temp的地址0x10000000,temp值为0x55,由于char类型只占用一个字节,那么temp变量就只占用0x10000000这个内存地址,不会占用其他内存地址,那假如变量是个int型呢?占用的字节数可能是4字节,这个时候内存和内存值又是怎么分配的呢?这个有待后面分析。
第二点,大小端只针对基本数据单元类型,那么什么是基本数据类型单元呢,char, int, float, double,那什么不是基本数据类型呢?例如:数组,结构体,联合等等。
第三点,先定义的位域因大小端情况会表示最高位或者最低位。

大小端影响了什么?

当基本数据类型占用字节数超过了1字节后,大小端决定了数据按照什么顺序存储在内存里

既然字节数超过了1个字节才有影响,那么就会一个疑问,char型数据占用字节数为1个字节,那么char型数据在大小端的模式下,会有什么不同吗?答案是没有。

什么是大小端?

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

这里有几个概念:高地址,低地址,高位,低位,其中高地址,低地址是针对内存地址而言,高位,低位是针对数据类型的bit位的高低而言。

如何根据具体情况分析

分析步骤:

  1. 首先找出基本数据类型,明确数据占用字节数以及高位,低位情况
  2. 明确变量地址始终指向变量的低地址
  3. 根据大小端的特性来套表格

举例:

例1(基本数据类型):int temp = 0x12345678;

假设 temp 的地址为 0x10000000 ,按照上面的分析步骤来拆分解析

  1. int型占用字节数为4字节,将数据按照字节为单位的高位,低位分解如下:0x12(高位),0x34,0x56 ,0x78 (低位)
  2. 由1点可知,基本数据类型占用内存为4字节,所以内存地址范围为 0x10000000~ 0x10000003
  3. 根据大小端的特性来套表格如下
大端模式
内存地址内存值步骤
0x100000000x124.依次取值
0x100000010x343.依次取值
0x100000020x56 2.依次取值
0x100000030x78 1.高地址存放低位
小端模式
内存地址内存值步骤
0x100000000x78 4.依次取值
0x100000010x56 3.依次取值
0x100000020x34 2.依次取值
0x100000030x12 1.高地址存放高位
例2(数组):short int temp[2] = {0x1234,0x5678};

假设 temp 的地址为 0x10000000 ,按照上面的分析步骤来拆分解析

  1. short int型占用字节数为2字节,将数据按照字节为单位的高位,低位分解如下:0x12(高位),0x34(低位),0x56 (高位),0x78 (低位)
  2. 由1点可知,基本数据类型占用内存为2字节,但是由两个元素,所以内存地址范围为 0x10000000~ 0x10000003
  3. 根据大小端的特性来套表格如下
大端模式
内存地址内存值步骤
0x100000000x122.依次取值
0x100000010x341.高地址存放低位
0x100000020x56 4.依次取值
0x100000030x78 3.高地址存放低位
小端模式
内存地址内存值步骤
0x100000000x34 2.依次取值
0x100000010x12 1.高地址存放高位
0x100000020x784.依次取值
0x100000030x563.高地址存放高位
例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 ,按照上面的分析步骤来拆分解析

  1. 首先分析位域情况

大端模式下,假设-表示0,则int值为0xCD000000,char值为0x28

大端下temp的int值位域分布如下

bit位313029282726252423222120191817161514131211109876543210
b1b2b2b3b3b3b4b4b4b4
bit值1100110100----------------------

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

bit位76543210
b5b5b5b5b5
bit值00101---

小端模式下,假设-表示0,则int值为0x0000011D,char值为0x05

小端下temp的int值位域分布如下

bit位313029282726252423222120191817161514131211109876543210
b4b4b4b4b3b3b3b2b2b1
bit值----------------------0100011101

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

bit位76543210
b5b5b5b5b5
bit值---00101
  1. int型占用字节数为4字节,char型占用字节数为1字节
  • 大端模式下将数据按照字节为单位的高位,低位分解如下:0xCD(高位),0x00,0x00,0x00(低位),0x28(字节)
  • 小端模式下将数据按照字节为单位的高位,低位分解如下:0x00(高位),0x00,0x01,0x1D(低位),0x05(字节)
  1. 由1,2点可知,基本数据类型占用内存为4字节+1字节,所以内存地址范围为 0x10000000~ 0x10000004
  2. 根据大小端的特性来套表格如下
大端模式
内存地址内存值步骤
0x100000000xCD4.依次取值
0x100000010x003.依次取值
0x100000020x002.依次取值
0x100000030x001.高地址存放低位
0x100000040x285.高地址存放低位
小端模式
内存地址内存值步骤
0x100000000x1D 4.依次取值
0x100000010x013.依次取值
0x100000020x002.依次取值
0x100000030x001.高地址存放高位
0x100000040x055.高地址存放高位

实验验证环境属于大端还是小端

测试代码如下:

#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 评论

留下您的评论.