结构体的内存对齐原则
什么是结构体?
结构体也是一种数据类型,但不是基本数据类型(如int、floatC中内置的类型)而是一种聚合(aggregate)类型,它的成员是基本数据类型或其它已定义的类型或自身类型的指针。
对结构体的基本概念有了大概认识后,就要进一步了解它在内存中的实现,而结构体的内存实现与内存对齐原则相关。在这之前可以先联想数组的内存实现
数组
考虑代码:
int main(void)
{
int int_arr[10] = {1,2,3}; //后面7个元素被初始化为值0
printf("&a[0]:%x\n"
"&a[1]:%x\n"
"&a[2]:%x\n",
&int_arr[0],&int_arr[1],&int_arr[2]);
return 0;
}
输出:
&a[0]:22fe20
&a[1]:22fe24
&a[2]:22fe28
内存中每个元素占4个存储单元(4字节),4个存储单元的位置是紧挨着的。
数组的内存实现——用一组连续的存储单元存储数组中的数据,逻辑上相邻的数组元素在内存位置上是相邻的。
结构体
考虑代码:
struct Block
{
float part1;
int part2;
};
int main(void)
{
struct Block test = {'a',20
};;
printf("&test:%x\n"
"&test.part1:%x\n"
"&test.part2:%x\n",
&test,&test.part1,&test.part2);
printf("sizeof(int):%d\n",sizeof(int));
return 0;
}
输出结果:
&test:22fe40
&test.part1:22fe40
&test.part2:22fe44
sizeof(int):4
结论:在内存中,结构体变量test的起始地址与其成员part1的地址相同,但成员part2并不是紧邻于成员part1,而是相隔4个字节。这是因为结构体的内存对齐原则:结构体成员的起始地址相对于结构体起始地址的偏移量是结构体成员自身所占内存大小的整数倍。可以理解成:这个地址偏移量对齐(整数倍)成员自身的大小。
可以计算:part2的地址减去test的地址,得到4(单位字节),刚好是int类型大小的一倍。