内存对齐之学会计算结果

一、内存对齐的原因
大部分的参考资料都是如是说的:
1、平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据 的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
2、性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。 原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。

二、对齐规则
每个特定平台上的编译器都有自己的默认“对齐系数”(也叫对齐模数)。程序员可以通过预编译命令#pragma pack(n),n=1,2,4,8,16来改变这一系数,其中的n就是你要指定的“对齐系数”。

规则:
1、数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后 每个数据成员的对齐按照#pragma pack指定的数值和这个数据成员自身长度中,比较小的那个进行。
2、结构(或联合)的整体对齐规则:在 数据成员完成各自对齐之后,结构(或联合)本身也要进行对齐,对齐将按照#pragma pack指定的数值和结构(或联合)最大数据成员长度中,比较小的那个进行。
3、结合1、2颗推断:当#pragma pack的n值等于或超过所有数据成员长度的时候,这个n值的大小将不产生任何效果。
4.、嵌套结构体的首地址遵循整体对齐
5、结构体中的数组就当拆分成一个个元素对齐
总结:
if代码指定了pack系数
整体对齐系数 = min((max(结构体中所有类型数据), pack)
else
整体对齐系数 = min((max(结构体中所有类型数据))
end
下面通过几个例子加深理解。todo:下面的例子都是默认在4字节对齐,vs2013运行的,括号代表是填充的字节

struct test1 {
int a;
char b;
short c;
char d;
};
上述没有指定对齐参数,整体对齐系数(all) = min(max(4,1,2)) = 4
1.数据成员对齐:
a ,4 = all,0%4=0,占据[0,3]
b,1 < all,4%1=0,占据[4]
c,2 < all,5%2~=0,所以[5]被填充,c占据[6,7]
d,1 < all,8%2 = 0,
总大小 = [0,8]=9
但是别忘了:
2.结构自身对齐,9%all ~= 0,最后总大小等于12,因为12%4 = 0
实际内存分布:a[0,3],b[4,5],c[6,7],d[8,11]

现在指定内存对齐
# pragma pack(1)
struct test1 {
int a;
char b;
short c;
char d;
};
# pragma pack()
整体对齐系数(all) = min(max(4,1,2),1) = 1
1.数据成员对齐:
a,4 > all,0%all=0,占据[0,3]
b,1 = all,4%1=0,占据[4],
c,2 > all,5%1=0,占据[5,6],
d,1 = all,7%1=0,占据[7]
2.结构自身对齐,8%all = 0
总大小等于8

# pragma pack(2)
struct test1 {
int a;
char b;
short c;
char d;
};
# pragma pack()
整体对齐系数(all) = min(max(4,1,2),2) = 2
1.数据成员对齐:
a,4 > all,0%all=0,占据[0,3]
b,1 < all,4%1=0,占据[4],
c,2 = all,5%all~=0,被填充5,占据[6,7]
d,1 < all,8%1=0,占据[8]
2.结构自身对齐,9%all ~= 0,总大小等于10,因为10%all = 0
实际内存分布:a[0,3],b[4,5],c[6,7],d[8,9]

嵌套结构体的情况
struct test1
{
char a;
int b;
struct
{
char c[5];
char d;
double e;
} inside;
int f;
char* g[6];
};
整体对齐系数(all) = min(max(4,1,2,8)) = 8
1.数据成员对齐:
a,1 < all,0%1=0,占据[0]
b,4 < all,1%4~=0,填充[1,2,3],占据4,5,6,7
inside的内部结构体的首地址8%all = 0,满足规则4
inside.c,1 < all,8%1=0,占据[8,9,10,11,12]
inside.d,1 < all,13%1=0,占据[13]
inside.e,8 = all,14%8 ~= 0,填充[14,15],占据[16,23]
f,4 < 24, 24%4=0,占据[24,27]
g,4 < all,28%4 = 0,占据4*6 ,就是[28,51]
2.结构自身对齐
52%all ~=0,所以总大小等于56,因为56%all = 0

# pragma pack(1) 这种情况就不写过程了,all = min(max(4,1,2,8),1) = 1
总大小等于所有长度之和 1 + 4 + 5 + 1+ 8 + 4 + 4*6 = 47
#pragma pack(2) 的情况,all = min(max(4,1,2,8),2) = 2
总大小等于 2(t填充1)+ 4 + 5 + 1 + 8 + 4 + 4*6 = 48

参考
http://www.cnblogs.com/tonydoen001/p/3564510.html
https://github.com/ludx/The-Lost-Art-of-C-Structure-Packing

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值