关于字节对齐

来源:互联网 发布:淘宝1个好评是几分 编辑:程序博客网 时间:2024/06/03 05:57

今天遇到一个选择题,一时之间把我弄糊涂了,原来字节对齐还有这个说法,记录一下。

#pragma pack(4)typedef union{short int a;char k[4];char c;}DATE;struct S{char a;DATE d;};sizeof(struct s);的值是几?一看也能知道结果应该是8吧,但是gcc 编译出来以后得出结果却是6
感谢在百度知道里面回答我问题的 听听-那冷雨 ,让我茅塞顿开那。
原因:结构体或者共用体中的成员的对齐值是:自身对齐值和系统对齐值中较小的那个。
 
DATE中的a的有效对齐值为2,余下的两个成员变量对齐值为1。
而结构头和共用体的对齐值取决于成员中对齐值较大的那个。
因此DATE的自身对齐值为2。
又因为DATE的大小为4 满足对齐要求。
对于S,a的对齐值为1,DATE对齐值为2,因此假设a从0地址开始存放,那么DATE必须从2开始存放,连续存放4个字节,这样S的大小为6,又因为S的自身对齐值为成员中较大的那个,就是DATE的对齐值:为2。 S的大小为6 正好满足。 综上:S占用6个字节。微笑
 
补充一下:
字节对齐取决于编译器,但是基本上有下面三个规则

①结构体变量的首地址能够被其最宽基本类型成员大小与对齐基数中较小者所整除。

②结构体每个成员相对于结构体首地址的偏移量都是该成员大小与对齐基数中较小者的整数倍。

 ③结构体的总大小为结构体最宽基本类型成员大小与对齐基数中的较小者的整数倍

但是这三条规则怎么看怎么难理解..还不如上面那一句话解释的容易接受。对齐基数等于是系统规定的字节对齐数值。

另外符合结构体的时候,寻找最宽基本类型成员的时候需要把结构体展开,但是在确定偏移量的时候要把结构体成员看做一个复合类型。

例如

#pragma pack(4)

struct A{

int a;

double d;

};

struct s{

int i;

struct A a;

char ch;

};

sizeof(struct s) = ?

在计算struct s的最宽字节的时候把A展开,double作为最宽字节,8字节,而对齐基数是4字节,因此结构体A的总大小只要满足是8和4之间较小的值的整数倍即可,12个字节。

所以在计算struct s的成员偏移量的时候又要把A看做一个整体,A a在struct s中的偏移量是该成员大小12字节和对齐基数4字节的较小者的整数倍 sizeof(int)=4字节正好。

所以四字节对齐的时候sizeof(struct s) = 20

如果是pack (8)的时候则sizeof(struct s) = 32.

 

结论:

还是用这句话理解比较好结构体或者共用体中的成员的对齐值是:自身对齐值和系统对齐值中较小的那个。

 

0 0
原创粉丝点击