字节对齐主要是针对结构体而言的,通常编译器会自动对其成员变量进行对齐,以提高数据存取的效率;
字节对齐有两种方式:默认对齐方式、指定对齐方式;
默认对齐方式
默认对齐方式内存分配满足以下三个条件:
结构体第一个成员的地址和结构体的首地址相同
结构体每个成员地址相对于结构体首地址的偏移量(offset)是该成员大小的整数倍,如果不是则编译器会在成员之间添加填充字节(internal adding)。
结构体总的大小要是其成员中最大size的整数倍,如果不是编译器会在其末尾添加填充字节(trailing padding)。
指定对齐方式
指定对齐方式使用以下方式声明:
#pragma pack(4)
指定对齐方式内存分配满足以下几个条件:
结构体第一个成员的地址和结构体的首地址相同
结构体每个成员的地址偏移需要满足:N大于等于该成员的大小,那么该成员的地址偏移需满足默认对齐方式(地址偏移是其成员大小的整数倍);N小于该成员的大小,那么该成员的地址偏移是N的整数倍。
结构体总的大小需要时N的整数倍,如果不是需要在结构体的末尾进行填充。
如果N大于结构体成员中最大成员的大小,则N不起作用,仍然按照默认方式对齐。
以下是指定对齐方式的测试代码:
#pragma pack(1)
typedef struct MyDATA
{
char name;
int age;
}DATA;
#pragma pack()
结果发现,当使用默认对齐时,sizeof(DATA) = 8;当使用指定对齐时,sizeof(DATA) = 5;可以发现,指定对齐为1时,基本上就避免了字节填充;如果我们想要恢复默认对齐,使用#pragma pack() 。
需要注意的是:在使用#pragma pack设定对齐方式一定要是2的整数幂,也就是(1,2,4,8,16,…),不然不起作用的,仍然按照默认方式对齐。
两种对齐方式的区别在于:默认对齐方式是每个成员地址的首地址偏移量是该成员大小的整数倍,而指定对齐方式则让该值变成了指定的n;
结构体每个成员地址相对于结构体首地址的偏移量:我们通常默认结构体首地址为0;
————————————————
版权声明:本文为CSDN博主「飞羚」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/wdl20170204/article/details/109386825