1.对齐的概念
对齐是指将数据(数据成员,结构体)存放在合适的内存地址上,以使CPU访问数据效率最大化。简单讲,数据只能存储在地址是数据大小整数倍的内存地址上。这里的数据可以是基本数据类型(char,int,short,float,double),也可以是复合数据类型(struct)。
比如,int a;变量a需要存储在能够被4(这里假设int为4个字节)整除的内存地址上,这样CPU在访问内存时只需访问一次即可。对于结构体也不例外,只是结构体包含多个数据项,要稍微复杂些。
注:
1)计算机中的内存地址是按字节进行编址的。
2)对齐是针对内存地址对齐。
2.对齐值
1)数据成员的对齐值:char型为1字节,short型为2字节,int/float型为4字节,double型为8字节。
2)结构体的对齐值:其成员中对齐值最大的那个值。结构体的对齐值主要考虑到存在结构体数组的情况(访问效率)。
3)指定对齐值:用#pragma pack(n)时的指定对齐值。
4)数据成员、结构体的有效对齐值:自身对齐值和指定对齐值中较小者,即有效对齐值=min(自身对齐值,指定对齐值)。
对于4),举个例子:
#pragma pack(4)
struct A
{
char a;
short b;
char c;
};
#pragma pack(0)
sizeof(struct A)=6
这里,并不是按4字节对齐,而是按自身对齐值进行对齐。char a按1(并没有按4,以下类同)字节对齐,short b按2字节对齐,因此,char a和short b之间需填充1个字节,char c按1字节对齐,这里已经有5个字节了,struct A按2字节对齐,char c后需填充1个字节,这样就是6个字节了。
同理,
#pragma pack(2)
struct A
{
char a;
float b;
char c;
};
#pragma pack(0)
sizeof(struct A)=8
这里,就是按指定2字节对齐。不具体分析了。
3.对齐规则
1)结构体变量的首地址能够被其最宽基本类型成员的大小所整除。
2)结构体每个成员相对结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal padding)。
3)结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节(trailing padding)。
例(int占4字节):
struct A
{
char a;
int b;
char c;
};
sizeof(struct A)=12
先分析结构体成员,char a按1字节对齐,占1字节,int b按4字节对齐,占4字节,char a,int b之间填充3个字节,char c按1字节对齐,共计9字节,再考虑结构体本身,struct A对齐值为int b的对齐值,按4字节对齐,char c后补充3字节。共计12字节。
3.指定对齐语法
1)语法1
#pragma pack(n)
#pragma pack(0) //恢复默认对齐值
2)语法2
#pragma pack(push) //保存原对齐值
#pragma pack(n)
#pragma pack(pop) //恢复原对齐值
语法2适合存在嵌套使用的情况。
————————————————
版权声明:本文为CSDN博主「propor」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/propor/article/details/131721643
|