结构体对齐方式

  1. 各个成员按照它们被声明的顺序在内存中顺序存储,第一个成员的地址和整个结构的地址相同。
  2. 每个基本类型有自己默认的对齐方式,通常是这个类型的大小
  3. 结构体默认的对齐方式是它的所有成员使用的对齐参数中最大的一个
  4. 结构体的长度必须是所用过的所有对齐参数的整数倍,不够就补空字节。

先来看几个例子

class struct1
{
short a;
long b;
};
struct struct2{
char c;
struct1 s1;
 short e;
};
int _tmain(int argc, _TCHAR* argv[])
{
	struct2 s2;
	cout<<sizeof(struct1)<<endl;
	cout<<sizeof(struct2)<<endl;
	cout <<((unsigned int)(&s2.s1) - (unsigned int)(&s2))<< endl;
    return 0;

}

上面的输出结果是:8 16 4

首先看一下struct1。short的默认大小是2字节,地址从0开始,占据前2个字节;long默认大小是4个字节,起始地址必须4字节对界,前面已经使用2个字节,需要补2个空字节,long占用[4-8]共4个字节。

struct2相对会复杂点。首先第一个字段是char,占用1个字节,没有问题。第二个字段是struct1,问题来了:struct1的对齐字节是多大?根据前面说的第3条规则,struct1的对齐字节是4(long的size>short的size),所以struct1前补3个空字节,struct1占用[4-11]8个字节;第3个字段是short,占用2个字节,且不需要补空字节。struct2到此总共占用了14个字节,但根据前面说的第4条规则:结构体的长度必须是所用过的所有对齐参数的整数倍,不够就补空字节。struct2使用过的对齐参数为1,8,2,最小的公倍数是16,因此struct2实际的size是16个字节。至于第3个表达式就不再解释了。

VC中提供了#pragma pack(n)来设定变量以n字节对齐方式。n字节对齐就是说变量存放的起始地址的偏移量有两种情况:第一、如果n大于等于该变量所占用的字节数,那么偏移量必须满足默认的对齐方式,第二、如果n小于该变量的类型所占用的字节数,那么偏移量为n的倍数,不用满足默认的对齐方式。结构的总大小也有个约束条件,分下面两种情况:如果n大于所有成员变量类型所占用的字节数,那么结构的总大小必须为占用空间最大的变量占用的空间数的倍数;否则必须为n的倍数。

下面举例说明其用法。
#pragma pack(push) //保存对齐状态
#pragma pack(4)//设定为4 字节对齐
struct test
{
char m1;
double m4;
int m3;
};
#pragma pack(pop)//恢复对齐状态
以上 结构体 的大小为16,下面分析其存储情况,首先为m1分配空间,其 偏移量 为0,满足我们自己设定的对齐方式(4 字节对齐 ),m1大小为1个字节。接着开始为m4分配空间,这时其 偏移量 为4,需要补足3个字节,这样使偏移量满足为n=4的倍数(因为sizeof(double)大于4),m4占用8个字节。接着为m3分配空间,这时其 偏移量 为12,满足为4的倍数,m3占用4个字节。这时已经为所有 成员变量 分配了空间,共分配了16个字节,满足为n的倍数。如果把上面的 #pragma  pack(4)改为 #pragma  pack(8),那么我们可以得到结构的大小为24。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值