c++内存对齐(图文详解)

内存对齐的作用

        1.提高cpu的内存访问速度

        cpu按块读取内存,一次读取一个块,块的大小可以是2、4、6、8个字节。

假如块的大小是4个字节,那么当一块数据的偏移量为4,起始地址为0,那么cpu刚好可以把0、1、2、3字节的所有数据读取到寄存器,但是假如数据的起始地址为1,那么cpu就需要读取两个块的数据,也就是首先读取0~3字节,再读取1~7字节的数据之后,再把5、6、7字节的数据移除,再合并1、2、3、4字节的数据才能进入寄存器。

        因此,当cpu没有进行内存对齐时,cpu会进行额外的处理才能把数据读取到寄存器,这降低了cpu的内存访问速度

        2.有利于平台移植

        不是所有硬件平台都能访问到任意地址上的任意数据,在嵌入式系统中,某些硬件只能在某些特定地址处取特定类型的数据,否则就会抛出异常,从而危及系统的安全性和稳定性。在这种情况下,内存对齐显然利于平台移植 

内存对齐的基本原则

  1. 结构体的第一个成员的偏移量为0,且每个成员的内存占用大小都是有效对齐值的整数倍,不足则补
  2. 结构体的总大小为有效对齐值的整数倍,不足则补。

有效对齐值的确定

  1. 当未明确指出有效对齐值时以结构体中占用内存最大的数据成员的内存大小为有效对齐值
  2. 当使用#prama(n)指出有效对齐值(n即为指出的有效对齐值)时,以n和结构体最大的数据成员大小的最小值作为有效对齐值。
  3. 当用__attribute__ ((packed))指定长度时,强制按照此值为结构体的有效对齐值

空类的内存大小

一个空类的占用内存大小为1个字节,并不是为0,有关空类的相关说明以及内存占用问题详见

c++空类的内存大小问题-CSDN博客

内置类型成员的对齐

case1

class A {
	char c1;
	char c2;
	int a;
};

类A的占用字节大小:8. 

1.确定类A的有效对齐值

也就是内存块的大小为4

n=max{sizeof(char),sizeof(int)}=4;

2.分析每个数据成员的内存占用情况:

c1:char占用1个字节,直接存放

c2:占用1个字节,1+1=2<4可以直接存放到上个内存块中

a:占用4个字节,2+4=6>4,也就是说整型a无法放入上一个内存块中,此时需要等待下一个内存块的到来,并直接存放

故类A的内存内存占用大小为1+1+(2)+4=8;

说明,括号内为补足字节

case2

class B {
	char c1;
	int a;
	char c2;
};

类B的占用字节大小:12

同case1分析,类B的有效对齐值也是4,则c1占用一个字节后,a无法存放一个块,故c1进行补足,之后a占用一个块,c2也占用一个字节后补足,故1+(3)+4+1+(3)=12

case3

class C {
	double d;
	int a;
	char c;
};

有效值为8(内存块大小),d占用一个块,a占用4个字节,c可以继续存放到a所占用的块

故为8+4+1+(3)=16

 

case4

class D {
	int a;
	double d;
	char c;
};

同上分析,有效对齐值为8,故总大小为4+(4)+8+1+(7)=24

结构体数据成员的对齐

问题:假如一个类中有一个结构体数据成员,那么这个类的内存占用大小该如何分析

class BigData
{
	char array[31];
};

class Data
{
	BigData bd;
	int integer;
};

void sol() {
	cout << __alignof(Data) << endl;//查看Data的有效对齐值
	cout << sizeof(BigData) << "   " << sizeof(Data) << endl;
}

首先确定Data的有效对齐值

在以上案例中,Data类中有一个数据成员是BigData类,而BigData类的有效对齐值为4,这是由于在BigData类中,数据成员Data类对象bd的有效对齐值为1,而BigData的另一个数据成员integer的大小为4,故BigData的有效对齐值为4。

事实上,当我们使用__alignof关键字查看int的有效对齐值时,结果为4也就是说对于内置类型的数据,它们的有效对齐值就是其占用大小本身。

确定了Data的有效对齐值后,再看每个数据成员的内存占用情况

bd成员共31个字节,不足4的整数倍,故补足一个字节,integer刚好占用一个块,故总大小为31+(1)+4=36

由上述实验我们可以得出结论,对于一个类的有效对齐值,取所有数据成员的有效对齐值的最大值作为该类的有效对齐值

继承的对齐

class A
{
	int i;
	char c1;
};

class B :public A
{
	char c2;
};

class C :public B
{
	char c3;
};

sizeof(C)结果是多少呢,gcc和vs给出了不同的结果,分别是8、16。

  • gcc:C相当于把所有成员i、c1、c2、c3当作是在一个class内部,(先继承后对齐)
  • vs:对于A,对齐后其大小是8;对于B,c2加上对齐后的A的大小是9,对齐后就是12;对于C,c3加上对齐后的B大小是13,再对齐就是16 (先对齐后继承)

参考:C++内存对齐_c++内存对齐原则_TABE_的博客-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值