出处:http://pppboy.blog.163.com/blog/static/30203796201082494026399/
http://blog.csdn.net/loverooney/article/details/38262709?ticket=ST-178747-gWh0gNJ1Qnzf7zCWMua7-passport.csdn.net
感谢博主的分享。
在看《C/C++程序员面试指南》(作者:杨国祥)中的结构体对齐时,原语句“每个数据都要对照结构体中最大数据的最小公倍数对齐”,和程序员面试宝典中所写有出入,宝典中所写“每个成员的存储起始位置能够被该成员的大小整除”。在网上查阅了几篇别人写的文章,以及在VS2010中仿真得出的结果证明《C/C++程序员面试指南》中描述错误。将一些细节知识点整理如下,方便回顾。
1、说明
字节对齐的基本原则:
1)结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
2)成员按照声明的顺序存储,每个成员相对于首地址的偏移量是该成员大小的整数倍;
3)整个结构体的总大小是最宽基本类型成员的整数倍。
对于结构体A的某成员是结构体B:
结构体A的大小是包括A中其他基本类型成员和B中所有基本类型成员中宽度最大的成员的整数倍。首先单独计算出B的总大小,设为M。接着计算A的总大小,在A中,B的起始地址能够被B中最宽数据成员大小整除,如若不够,需要补充空字节。在A中,B所占大小为M。B之后的数据的起始地址能够被该数据的大小整除,如若不够,需在B之后补充空字节。
结构体中包含数组时,在计算最宽成员长度时,将数组元素当成独立的个体。例:
struct sample1{
int a;
char b[5];
}
sample1的最宽长度为int型,4个字节。sample1的大小为:4+5+补3个字节 = 12个字节。
空结构体占用1字节。
2、计算方法
以32字节的系统为例
sizeof(char) = 1; sizeof(int) = 4; sizeof(long) = 4; sizeof(double) = 8;
//空 sizeof(S0) = 1;
struct S0{ };
//sizeof(S1) = 8. b为字节最宽的数据,占用4个字节。a起始地址为0,占用1个字节,补3个字节,b的起始地址为4,占用4个字节,4~7。共8字节。
struct S1{
char a;
long b;
};
//sizeof(S2) = 8. b为字节最宽的数据,占用4个字节。起始地址为0,0~3,a占用1个字节,起始地址为4,为了使总大小为b的整数倍,a补充3个字节。共8个字节。
struct S2{
long b;
char a;
};
//sizeof(S3) = 16. 将S1的成员代入,最宽数据为S1.b,4个字节。c占用1字节,d的起始地址要能够被d中最宽数据大小整除,在c后补充3空字节,d占用8字节,e占用4字节。共16字节。若将long e 换为double e,则最宽数据为e,8字节。
c占1字节+补3字节+d占8字节 = 12字节,不能被e的8字节整除,在d后需补4个空字节。
总大小为:12+4+8 = 24字节
struct S3 {
char c;
struct S1 d;//结构体
long e;
};
//sizeof(S4) = 8,static存储在静态存储区域内,不算在内。
struct S4{
char a;
long b;
static long c; //静态
};
//sizeof(S5) = 16. 最宽数据为b,name按照单个元素的大小1字节与其他数据进行比较。a占1字节,补3字节,0~3,b占4字节,4~7,name占5字节,不能被8整除,需在b后补2字节,此时,共15字节,不能被4整除,在name后补1字节。总大小为16字节。
struct S5{
char a;
long b;
char name[5]; //数组
};
//sizeof(student0) = 16,最宽数据为num,4字节。name5字节,补3字节,num4字节,score2字节,补2字节。总大小为16字节。
struct student0
{
char name[5];
int num;
short score;
};