结构体内存对齐原则

C/C++中,最常见的数据类型有char,int,short,float ,double,long等,在各个系统或编译器中可能所占的字节数不太一样,此文围绕win7 64位,vs2015环境下来讲解。先看下图通过sizeof获得的各个类型所占字节数:
相信看此文的人对什么是结构体,为什么要用结构体已经很熟悉了,不再赘述。直接看它的对齐原则:

在内存中,声明一个结构体对象它所占的内存中的数据成员是按声明顺序排放的,但并不是紧密排列的。从结构体存储的首地址开始,每个元素放置到内存中时,它都会认为内存是按照自己的大小来划分的,因此元素放置的位置一定会在自己宽度的整数倍上开始。先说具体对齐原则,再引用几个例子相信就很清楚了。

对齐原则:

用msdn的一句话来讲就是结构体中的数据成员,除了第一个是始终放在最开始的地方,其它数据成员的地址必须是它本身大小或对齐参数两者中较小的一个的倍数。

注:默认对齐参数解析:在windows中,VS编译器下,默认对齐数为8; ,在Linux中,默认对齐数为4,也可以根据#progma pack(number)来修改,不过这个number只能为系统一些内置数据类型的大小,即number只能设为1,2,4,8,不能够设3,5等等

例1:

struct _node
{
	char ch;
	double d;
	int i;
};

如果按照顺序相加来运算的话,定义一个结构体对象所占的字节数应该是1+8+4=13,而实际该结构体对象的大小为24字节。计算方法,min(8,8)=8,所以此处每一个元素的起始位置都要是自己的大小的整数倍。ch所占0位置,下一个应该是位置1,但是由于1不是8的倍数,所以1-7为空闲,d从8开始存放,即d所占空间为8-15,下一个位置是16,由于16是4的整数倍,所以i从16开始到19结束,整体+1后为20,由于,而20不是8的整数倍,所以向后偏移至24,所以结构体的大小为24字节。


例2:此时设置一下对齐字节

#pragma pack(4)
struct _node
{
	char ch;
	double d;
	int i;
};

此处区别就是设置了对齐参数为4,也就是说在这个结构体中,ch的起始位置需要是min(1,4),double的起始位置需要是(8,4),int的起始位置需要是(4,4),所以,ch占0位置处,1不是4的倍数,所以1-3空闲,d占4-11,由于12是4的倍数,所以i占12-15,加一后等于16,此时正好是4的倍数,所以结构体所占大小为16


猜你喜欢

转载自blog.csdn.net/hlw0522/article/details/79953720