1.什么是结构体内存对齐和为什么要对齐?
元素是按照定义顺序一个一个放到内存中去的,但并不是紧密排列的。从结构体存储的首地址开始,每个元素放置到内存中时,它都会认为内存是按照自己的大小来划分的,因此元素放置的位置一定会在自己宽度的整数倍上开始。
2.结构体内存怎样对齐?
1.先介绍一个相关的概念——偏移量。偏移量指的是结构体变量中成员的地址和结构体变量地址的差。结构体大小等于最后一个成员的偏移量加上最后一个成员的大小。显然,结构体变量中第一个成员的地址就是结构体变量的首地址。
2.该数的偏移量必须是该数大小的整数倍,否则偏移量就自动变为该数的最小倍数,然后再计算(0被看作任何数的整数倍)。
for example 1:
struct stu1
{
int i;
char c;
int j;
};
第一个成员i的偏移量为0,i的大小为4,偏移量满足上述条件2,则第二个数的偏移量为0+4 = 4;c的大小为1,满足2,则j的偏移量为5,但不满足条件2,所以j的偏移量变为j大小的最小倍数为8,故结构体大小=最后一个成员的偏移量+最后一个成员的大小= 8 + 4 = 12。
for example 2
struct stu2
{
int p;
short o;
};
成员p的偏移量为0;成员o的偏移量为4,都不需要调整。但计算出来的大小为6,显然不是成员p大小的整数倍。因此,编译器会在成员o后面补上2个字节,使得结构体的大小变成8从而满足第二个要求。由此可见,大家在定义结构体类型时需要考虑到字节对齐的情况,不同的顺序会影响到结构体的大小
for example 3
struct stu5
{
short i;
struct
{
char c;
int j;
} ss;
int k;
}
结构体stu5的成员ss.c的偏移量应该是8,而不是 5。整个结构体大小应该是20。
3.对齐参数如何设置?可以设置为按照任意字节数对齐吗?
在windows中,VS编译器下,默认对齐数为8;
在Linux中,默认对齐数为4
设置对齐参数可在结构体struct之前加上#pragma pack(对齐数),在struct之后加上#pragma pack;便可以设置对齐参数。
#pragma pack(4)
struct A
{
int a;
char b;
double c;
char d;
};
#pragma pack;
需要注意的是对齐参数不能任意设置,只能是内置类型已有的字节数,如:char(1)、short(2),int(4),double(8)…不能是3,5…任意数。