那天在网上看了这么一道题目,忽然自己想去搞搞清楚,所以翻资料,整理、测试,得出一个算法来,我把思想记录下来:
得到了以下结论:
1. 成员的对齐是按声明顺序进行的;
2. 对齐值由编译指示和最大成员两者较小的值决定;
3. 未对齐到对齐值的成员一起形成块对齐(联合对齐);
4. 上一个(下一个)对齐采用自己较大则不变,自己较小则填充自己对齐到上一个(下一个)大小;
5. 每成员对齐:如果前面已对齐到对齐值,下一个对齐自己。如果前面未对齐到对齐值,如果加上下一个成员不大于对齐值,下一个对齐自己,否则填充自己块对齐到对齐值。
6. 最后还未对齐到对齐值的,填充空间块对齐到对齐值。
这个可能是套话,大家看下面的计算公式吧,很直观和简单。
我们默认编译器是8字节大小(机器不同可能会有别,我用VS2005做的测试)
class a
{
public:
double e;//8
int ttt;//4
char t;//1
public:
a();
~a();
public:
virtual double bbo();//8
};
看看上面的函数,这个计算的结果是24
看一下怎么进行的对齐呢?
遵照上面的规则来计算,公式为:8+4+4+8=24,因为int是4个字节,char是1个字节,而4+1=5<8,所以int和char要进行联合对齐了,一共占8个字节,只能每个分到4个字节了!
class a
{
public:
int ttt;//4
double e;//8
char t;//1
public:
a();
~a();
public:
virtual double bbo();//8
};
看下这个呢?我把double房到了int的下面,这样算出来的结果是32,编译器遵从从上到下的方式来进行逐个计算的。
8+8+8+8=32;
再来看下面的例子
class a
{
public:
double e;
int ttt;
char t;
int tog;
public:
a();
~a();
public:
virtual double bbo();
};
8+4+4+8+8 = 32;
class a
{
public:
double e;
int ttt;
char t;
char tog;
public:
a();
~a();
public:
virtual double bbo();
};
8+4+2+2+8=24;
从这几个例子中大家可以很清楚该怎么计算了吧?
还有几点需要描述:
1.自然对界(natural alignment)即默认对齐方式,是指按结构体的成员中size最大的成员对齐。
struct naturalalign
{
char a;
short b;
char c;
};
那大小就是2+2+2=6,因为最大的是short为2个字节,对齐就是6了。
2.指定对界
一般地,可以通过下面的方法来改变缺省的对界条件:
· 使用伪指令#pragma pack (n),编译器将按照n个字节对齐;
· 使用伪指令#pragma pack (),取消自定义字节对齐方式。
注意:如果#pragma pack (n)中指定的n大于结构体中最大成员的size,则其不起作用,结构体仍然按照size最大的成员进行对界。