您的位置:首页 > 其它

关于结构体内存对齐规则的整理及思考

2014-04-04 23:21 274 查看
        最近两天看了一些关于结构体内存对齐的文章,便想把它们整理一下,也加入了一点自已的思考,只当为自己理清思路,如果有误,还望大家指正。

一、为什么要内存对齐

       内存对齐,主要是为了提高CPU的效率。关于这个问题,这篇文章讲得很好《Data alignment: Straighten up and fly right》,我怕自己表述不清楚,所以还是请大家直接看这篇文章。

二、结构体内存对齐的规则

       结构体内存对齐的要求,就是要确保结构体中的每一个数据成员,其起始地址是该数据成员所占字节数的整数倍。为了满足这一要求,便有了如下这些规则:
2.1 一个结构体对象的起始地址(也等于该结构体对象的第一个数据成员的地址),一定是该结构体中最大成员的整数倍;

2.2 结构体的数据成员中,第一个数据成员的的偏移量为0,其余数据成员的偏移量,必须是其自身大小的整数倍;

2.3 结构体的总大小,也就是sizeof的结果,必须是其内部最大成员的整数倍,不足的要在最后一个数据成员之后补齐;

2.4 如果一个结构体A中包含有另一结构体B或数组(数组此时可看做特殊的结构体),则B在A中的偏移量必须是B中最大数据成员的整数倍。

三、为什么会有上述四条规则

       我们知道,一个结构体对象中,某数据成员的地址(记为A),应该等于该结构体对象的起始地址(记为B),加上该数据成员在该结构体中的偏移量(记为C)。即:A = B + C,要保证A为该数据成员大小的整数倍,一种可行的方法是让B和C都为该数据成员大小的整数倍。
       规则2.1中,规定B应该是该结构体中最大数据成员的整数倍,也就意味着,B是该结构体中每一个数据成员大小的整数倍,再加上规则2.2,就可以保证,该结构体对象中每一个数据成员都可以满足结构体内存对齐的要求(第二段中红字)。
       对于单个结构体对象,规则2.1和2.2足以使其满足结构体内存对齐的要求,之所以还要满足规则2.3,是出于对结构体数组的考虑。对于结构体数组而言,需要让该数组中的每一个元素都满足规则2.1和2.2,但对于任何数组,数组中的元素都必须连续存储,所以在有些情况下,就必须对结构体进行补齐。而只要满足了规则2.3,就恰好可以确保结构体数组中的每一个元素都满足规则2.1和2.2。
       接下来考虑复杂一点的问题,考虑如下定义的2个结构体:
struct M
{
char c;
double d;
};

struct N
{
int i;
M m;
};

       结构体M的对象m作为了结构体N的数据成员。遇到这种情况时,对于结构体M的内存是如何对齐的,我想看了前边的分析后大家应该都比较清楚,而对于结构体N,其包含的数据成员m,是否应该当做一个整体来对待?我们最终的目的,是使得N中所有的数据成员(包括包含在m中的c和d),都满足结构体内存对齐的要求。我们知道如何让N中的数据成员i对齐,那么如何让m中的c和d也对齐呢,c和d在m中的偏移量由规则2.2指出,而c和d的最终地址,还得加上m的地址,而m的地址又等于m在N中的偏移量加上N的地址,所以就有了规则2.4,要求m在N中的偏移量应等于m中最大数据成员的整数倍,同时要求,N的起始地址,应当是N的所有数据成员(即i,c,d)中,占用空间最大的那一个(即d)的整数倍。



四、参考

1.http://www.ibm.com/developerworks/library/pa-dalign/
2.http://blog.csdn.net/21aspnet/article/details/6729724
3.http://blog.csdn.net/hairetz/article/details/4084088
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  内存 struct sizeof