您的位置:首页 > 其它

关于结构体的对齐

2012-05-02 11:17 225 查看
昨天晚上和朋友讨论面试题目,讲到字节对齐的题目。对于字节对齐以前了解过,但是昨晚一翻讨论下来发现自己以前的理解还不够到位。于是有花时间又研究了下。于是有了本随笔,仅做备忘。

(1)首先需要知道对齐模数这个概念,
在32位windows平台
类型 char short int long float double
对齐模数 1 2 4 4 4 8
在32位linux平台

类型   char short int long float double
对齐模数  1 2 4 4 4 4
(2)其次需要知道#pragma pack(n),编译选项。不妨把n称为额定对齐模数。
这个编译选项的作用是告诉编译器如何处理这些对齐模数。
如果我们没有显式声明这个编译选项,则默认为#pragma pack(8).
编译器对于这个编译选项的用法原则是,当处理一个变量,取这个变量类型的对齐模数和额定对齐模数的最小值,实际对齐按这个最小模数来。
(3)对于一个结构体,内部数据成员的安放顺序由于对齐模数的存在将会使得整个结构体的size发生变化。
(4)在结构体的末尾,假设我们按照对齐模数算出大小为size0,但是由于struct类型本身也需要进行额外的对齐,
那么编译器取出结构体中所有数据成员中的最大的那个对齐模数和额定对齐模数进行比较,得出最小值,如果size0是这个
最小值的倍数则无需额外补齐,否则补齐至这个最小值的倍数为止。

结合实例分析是
(1)//vc++默认的额定对齐模数是8,g++编译器好像也是的
struct s1 {
char c,*ptr;
union{
double a;
int c:2,d:1;
};
struct s1 *next;
};
c的有效对齐模数是1,ptr的有效对齐模数是4,例子中的union的有效对齐模数是8(在linux 平台是4),next指针变量的有效对齐模数是4,
所以c占内存[0],ptr对齐到内存4,占内存[4~7],union的对齐模数是8,现在刚好是8,不用对齐,占内存[8~15],next占内存[16~19].分析到这里总共占了size0=20字节。
然而对于struct需要额外补齐,所以windows平台下size0补齐到8(这个8是double的模数和额定对齐模数比较的最小值)的倍数即24.
linux平台下由于20是4的倍数不用进行额外补齐,最后答案是20。

(2)struct s3{

union{

unsigned int c:2,d:1;
double a;
int b;
};
char c1a[16];
int cha1;
int cha2;
int * t1;
};
windows平台下
union占[0~7],cla占[8~23],cha1占[24~27],cha2占[28~31],t1占[32~36],最后对struct进行额外补齐,答案是40.
如果将cla[16]改成cla[20],有一样的分析:union占[0~7],cla占[8~27],chal占[28~31],cha2占[32~35],t1占[36~39],总和为40已经是8的倍数,无需进行额外补齐。
linux平台下,可以自己分析下。cla[16]的情况对应size是36字节,cla[20]对应情况是40字节。

====================================================================

时隔两年,又了解到了__declspec的相关使用,__declspec(align(n)) 修饰符也会对结构和变量的对齐产生影响,具体参见这篇博文http://www.cppblog.com/deercoder/archive/2011/03/13/141747.html。

关于__declspec修饰符的具体用法,参考http://blog.csdn.net/iamoyjj/article/details/4195635。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: