在此,首先感谢 hi_wyl 的文章《#progma整理》给我的重要提示(原则的第一条),
内存对齐问题困扰了我许久,为了便于大家的理解,结合该文中对内存对齐部分的讲述,我对其进行了整理,以及细节方面的扩充。
希望能够为大家的理解带来方便,若有漏洞及错误,望大家指正。
该文的网址为:http://blog.csdn.net/hi_wyl/article/details/1698646
内存对齐方式的原则 :
1. 成员的对齐是按声明顺序进行的;(这个很重要)==》见例1
2:在VC环境下的默认对齐值为8,PS:因为最大的非自定义类型对齐值为8。
3:由于对齐是按照声明顺序进行对齐的,所以这就里就会出现一些对当前成员对齐方式的影响因素:
为了方便理解,我们这边设定几个变量
A:val_self(成员自身的对齐值 如int型为4)
B:val_total(编译指示对齐值(可通过#pragma pack 进行指定,若无强制规定,则默认为8)和最大结构体成员对齐值中的较小值;)
影响因素1:首先,第一个声明的成员对齐值取val_total进行对齐;
影响因素2:(若非第一个声明的成员)看前一个声明的成员内存对齐之后的状况:
case1:若果上一个成员对齐后,所分配给其的空间剩余,且该剩余空间满足如下条件:
条件1: 该剩余空间中存在偏移值为当前成员val_self的整数倍的字节块。
条件2: 而且从该偏移算起,加上val_self仍不超出剩余空间的大小。
则当前成员填充到从该偏移算起的内存中。
例:
struct test //val_self 为1; val_total为8
{
char cA; //首先按照val_total来分配内存,char占一个,剩余7个
int iB;//上一个成员分配的空间剩余,且有偏移量为4的空间,而且4+4(int的val_self)==8,没有超过剩余空间,于是iB就填充到从偏移量为4开始的连续4个空间中。
double dC;//
};
case2:如果上一个成员内存分配后没有剩余空间,或者可以填充的起始偏移值加上自身的val_self超过了剩余空间大小,则当前成员仍按照val_total来分配内存。
接上例:
struct test //val_self 为1; val_total为8
{
char cA; //首先按照val_total来分配内存,char占一个,剩余7个
int iB;//上一个成员分配的空间剩余,且有偏移量为4的空间,而且4+4(int的val_self)==8,没有超过剩余空间,于是iB就填充到从偏移量为4开始的连续4个空间中。
double dC;//因为上一个成员iB分配完后没有剩余空间,所以自己按照val_total来分配8个空间。
};
综上,struct test的size为:8(1 + 3(空出来) + 4) + 8 == 16
********************************************************
例1:声明顺序的重要性
struct sample5
{
char a; ///1
double b; ///8
char c; ///4
int d; ///1
char e;
}; 32==》 8 + 8 + 8(1 + 3(空) + 4) + 8
struct sample5
{
double c; ///8
char a; ///1
char b; ///4
int d; ///1
char f;
}; 24 ==》8 + 8(1 + 1 + 2(空) + 4 ) + 8
以上的测试都是在VC环境下。