面试题答案
一键面试定义柔性数组
在C99标准中,结构体的最后一个成员可以是大小未知的数组,这就是柔性数组。定义方式如下:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int num;
int arr[]; // 柔性数组
} FlexArray;
初始化
初始化柔性数组需要动态分配内存,不仅要为结构体本身分配内存,还要为柔性数组部分分配足够的空间。例如:
FlexArray* createFlexArray(int num, int size) {
FlexArray* fa = (FlexArray*)malloc(sizeof(FlexArray) + size * sizeof(int));
if (fa == NULL) {
return NULL;
}
fa->num = num;
for (int i = 0; i < size; i++) {
fa->arr[i] = i; // 初始化数组元素
}
return fa;
}
释放内存
释放内存时,只需要释放结构体的指针,因为结构体和柔性数组的内存是连续分配的。
void freeFlexArray(FlexArray* fa) {
free(fa);
}
与普通动态数组初始化方式的比较
- 优势:
- 内存连续:柔性数组使得结构体和数组的内存是连续分配的,在访问数组元素时缓存命中率更高,提高了访问效率。例如在遍历柔性数组时,由于内存连续,CPU缓存可以更有效地工作,减少内存访问次数。
- 内存管理方便:在分配和释放内存时,只需要操作一个指针,简化了内存管理。相比于普通动态数组可能需要分别管理结构体和数组的内存,柔性数组只需要一次
malloc
和一次free
操作。
- 劣势:
- 灵活性稍差:普通动态数组在分配内存时更加灵活,可以根据需要随时调整大小。而柔性数组一旦分配,大小就固定了(虽然在定义结构体时大小未知,但分配内存时就确定了)。例如在需要动态扩展数组大小的场景下,普通动态数组可以通过
realloc
等函数方便地实现,而柔性数组则需要重新分配更大的内存并复制数据。 - 内存浪费风险:如果对柔性数组大小估计不准确,可能会导致内存浪费。例如分配了过大的柔性数组空间,但实际使用的元素很少,就会造成部分内存没有被充分利用。
- 灵活性稍差:普通动态数组在分配内存时更加灵活,可以根据需要随时调整大小。而柔性数组一旦分配,大小就固定了(虽然在定义结构体时大小未知,但分配内存时就确定了)。例如在需要动态扩展数组大小的场景下,普通动态数组可以通过