内存对齐规则和实战
这篇文章是我的平时的一个笔记修改后来的。这里主要介绍一下内存对齐的规则,以及提供一些实战一下。几篇我觉得比较好的详细的介绍内存对齐的作用什么的博文会在文末附上。
规则
在开始实战前,需要了解下规则。
首先了解变量的有效对齐值N
-
数据类型对齐值自身的对齐值:也就是基本数据类型的自身对齐值 如int 为4字节, char为1字节
-
指定对齐值:#pragma pack (value),这个宏中的value就是指定对齐值
-
结构体或类的自身对齐值:MAX(其成员变量自身对齐值)
-
数据成员、结构体和类的有效对齐值:MIN(自身对齐值,指定对齐值)
规则一
每个成员的起始地址应满足 “起始地址%N == 0”
规则二
结构体的有效对齐值要圆整(就是结构体成员变量占用的总长度需要是对结构体 有效对齐值 的整数倍)
<font color="blue>"总长度 % 有效对其值 == 0
实战
示例
先看一个例子运用一下规则,热热身。
可以先分析下,成员变量的有效对齐值是什么,然后要满足规则一和规则二,变量的存储地址要后移多少,最后算出的结构图的总长度是多少。(这里没有#pragma pack())
struct A
{
int a;
char b;
short c;
};
示例分析
- 首先确定每个成员的有效对齐值 因为没有指定对齐值 所以为自身数据类型的对齐值
a--4字节 b--1字节 c--2字节
- 起始地址必须满足规则一“起始地址%N = 0”
令起始地址位0x0000 按照变量的顺序存储<br>
变量a的起始地址 0x0000%4 = 0;满足条件 占用4个字节 0x0000--0x0003 占四个字节变量
b 的起始地址 是 0x0004%1 = 0满足条件 占用一个字节 就是0x0004
变量c 的起始地址 是 0x0005%2 !=0 所以起始地址要向后移位 直到满足条件位置 0x0006%2 = 0
满足条件 占用2字节 0x0006-- 0x0007
所以结构体总共占用了8字节
- 根据结构体的有效对齐值圆整
结构体的有效对齐值是 其成员中自身对齐值最大的那个值为4
由于8字节正好是4的整数倍 所有就是8字节
实战开始
上面分析了一次,下面可以进行实战了。下面加上了#pragma pack(),所以需要注意这里的有效对齐值是什么了,回顾前面MIN(自身对齐值,指定对齐值)。
实战1
#pragma pack(4)//指定对齐值
struct B
{
char b;
int a;
short c;
};
union C
{
int a[5];
char b;
double c;
};
struct D
{
int n;
C a;
char c[10];
};
实战2
#pragma pack(8)//指定对齐值
struct example1
{
short a;
long b;
};
struct example2
{
char c;
example1 struct1;
short e;
};
简单分析在下划线下面
内存单元从0开始编号
实战1分析
#pragma pack(4)//指定对齐值
struct B //10 + 2(圆整) = 12
{
char b;//[0]
int a;//[1]...[4]...[7]([1]...[4]表示地址后移到单元[4])
short c;//[8]...[9]
};
union C //20字节 联合体按成员所占最长单元算
{
int a[5];
char b;
double c;
};
struct D // 34+2(圆整) = 36
{
int n; // [0]...[3] (4个字节)
C a; // [4]...[23] (20字节)
char c[10]; // [24]...[33] (10字节)
};
实战2分析
#pragma pack(8)
struct example1//8
{
short a;//[0]...[1]
long b;//[2]...[4]...[7]
};
struct example2//14+2(圆整)=16
{
char c;//[0]
example1 struct1;// [1]...[4]...[11]
short e;//[12]...[13]
};
悄悄附上我的测试代码运行的截图
嗯 写了一些,还是以理解规则然后实战为主,附上详细的他人的博文,参考参考。
博文