面试题答案
一键面试内存对齐对calloc
分配内存大小及数据存储的影响分析
- 内存对齐规则:
- 不同类型的数据在内存中存储时,其起始地址需要满足一定的对齐要求。例如,
char
类型通常以1字节对齐,int
类型在32位系统上通常以4字节对齐,double
类型通常以8字节对齐。 - 结构体的大小不是简单地将其成员大小相加,而是要考虑内存对齐。结构体的大小是其最大对齐成员大小的整数倍。并且每个成员相对于结构体起始地址的偏移量必须是该成员对齐字节数的整数倍。
- 不同类型的数据在内存中存储时,其起始地址需要满足一定的对齐要求。例如,
- 对
calloc
分配内存大小的影响:- 当使用
calloc
分配结构体数组内存时,calloc
分配的总内存大小不仅要满足结构体成员大小之和,还要满足内存对齐要求。例如,如果一个结构体由于内存对齐其大小为16字节(假设结构体成员实际大小之和为10字节,但因对齐要求为16字节),要分配10个这样的结构体数组,calloc
分配的内存大小为16 * 10 = 160字节,而不是10 * 10 = 100字节。
- 当使用
- 对数据存储的影响:
- 内存对齐保证了不同类型数据在内存中的存储地址符合其对齐要求,这样可以提高CPU访问内存的效率。例如,对于一个
int
类型数据,如果它存储在4字节对齐的地址上,CPU可以更高效地读取它。在结构体数组中,每个结构体实例内的成员按对齐规则存储,结构体实例之间也按对齐规则排列。
- 内存对齐保证了不同类型数据在内存中的存储地址符合其对齐要求,这样可以提高CPU访问内存的效率。例如,对于一个
代码验证
#include <stdio.h>
#include <stdlib.h>
// 定义一个结构体
typedef struct {
char c;
int i;
double d;
} MyStruct;
int main() {
// 分配一个包含5个MyStruct结构体的数组
MyStruct *arr = (MyStruct *)calloc(5, sizeof(MyStruct));
if (arr == NULL) {
perror("calloc");
return 1;
}
// 输出结构体的大小
printf("Size of MyStruct: %zu bytes\n", sizeof(MyStruct));
// 输出分配的总内存大小
printf("Total allocated memory: %zu bytes\n", 5 * sizeof(MyStruct));
// 释放内存
free(arr);
return 0;
}
在上述代码中:
- 定义了一个
MyStruct
结构体,包含char
、int
和double
类型成员。 - 使用
calloc
分配了一个包含5个MyStruct
结构体的数组。 - 输出了
MyStruct
结构体的大小以及calloc
实际分配的总内存大小。可以看到,由于内存对齐,MyStruct
结构体的大小不是简单的1 + 4 + 8 = 13
字节,而是16字节(double
类型对齐要求为8字节,结构体大小需为8的整数倍),因此分配5个结构体的数组,总内存大小为5 * 16 = 80
字节。