1.什么是柔性数组
C99 中,结构中的最后一个元素允许是未知大小的数组,这就叫做『柔性数组』成员。
struct S
{
int i;
char c;
char arr[0];//柔性数组//也可以把0省略掉
};
2.柔性数组的特点
我们先来计算下含有柔性数组的结构体的大小。以上面为例。
printf("%",sizeof(struct S));
结果
为什么是8?这关系到柔性数组的特点:
-
sizeof 返回的这种结构大小不包括柔性数组的内存。
-
结构中的柔性数组成员前面必须至少一个其他成员。我们发现去掉柔性数组,结构体的大小刚好是8。如果柔性数组前没有成员,那么结构体大小就是0,结构体就不存在。
-
包含柔性数组成员的结构用malloc ()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。
例子
struct S
{
int i;
char arr[0];
};
int main()
{
struct S* p = (struct S*)malloc(sizeof(struct S) + sizeof(char) * 10);
printf("%d", sizeof(struct S));
free(p);
p = NULL;
return 0;
}
结果
3.柔性数组的使用
struct S
{
int i;
char arr[0];
};
int main()
{
struct S* p = (struct S*)malloc(sizeof(struct S) + sizeof(char) * 10);
if (NULL == p)
{
perror("malloc");
return 1;
}
//对柔性数组赋值
int i = 0;
for (i = 0; i < 10; i++)
{
*(p->arr + i) = i + 97;//97是a的ASCII码值
}
//对柔性数组打印
for (i = 0; i < 10; i++)
{
printf("%c ", *(p->arr + i));
}
free(p);
p = NULL;
return 0;
}
结果
4.柔性数组的优势
上面例题还有第二种做法,通过对比得出优势
struct S
{
int i;
char *arr;//改为指针
};
int main()
{
struct S* p = (struct S*)malloc(sizeof(struct S));
if (NULL == p)
{
perror("malloc");
return 1;
}
p->arr = (char*)malloc(sizeof(char) * 10);
if (NULL == p->arr )
{
perror("malloc");
return 1;
}
//对柔性数组赋值
int i = 0;
for (i = 0; i < 10; i++)
{
*(p->arr + i) = i + 97;//97是a的ASCII码值
}
//对柔性数组打印
for (i = 0; i < 10; i++)
{
printf("%c ", *(p->arr + i));
}
free(p->arr );
p->arr = NULL;
free(p);
p = NULL;
return 0;
}
这种方法同样可以达到我们想要的效果,但第一种方法更好,为什么?
- 法1一共malloc一次、free一次、i和arr连续,法2一共malloc两次、free两次、内存不连续。
- 法1不容易出错,方便内存释放,只需释放一次。其成员没有申请空间不用释放,而法2的成员有申请空间,需要再释放一次。
- 法2malloc次数越多,内存碎片越多,内存空间的利用率越低;同时法1由于内存连续,有利于访问速度。