1、什么叫变长结构体?
如下所示:
struct var_st
{
int len;
char data[0]; //c99支持
};
sizeof(struct var_st)=4;
注意
可能有的编译器不支持char data[0];需要用char data[1]代替,这样上面结构体大小是sizeof(struct var_st)=8(字节对齐);
那结构体是怎么实现可变长的呢?
如上所示,结构体中的最后一个元素是一个没有元素的数组。我们可以通过动态开辟一个比结构体大的空间,然后让data去指向那些额外的空间,这样就可以实现可变长的结构体了。更为巧妙的是,我们甚至可以用len存储字符串data的长度。
示例代码1
用[0]的数组
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct var_st
{
int len;
char data[0];
};
int main()
{
int len = 10; //需要多开辟10个字节的空间
char str[10] = "123456789";
printf("sizeof(struct var_st) = %d\n",sizeof(struct var_st));
struct var_st *my_data = malloc(sizeof(struct var_st)+len); //申请足够大的内存空间
memcpy(my_data->data,str,len);
printf("my_data's data is:%s\n",my_data->data);
free(my_data); //直接释放内存
return 0;
}
运行结果
示例代码2
用指针指向数据域部分
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct var_st
{
int len;
char *data;
};
int main()
{
int len = 10;
char str[10] = "123456789";
printf("sizeof(struct var_st) = %d\n",sizeof(struct var_st));
struct var_st *my_data = malloc(sizeof(struct var_st));
my_data->data = (char*)malloc(len); //为数据域单独开辟内存空间
memcpy(my_data->data,str,len);
printf("my_data's data is:%s\n",my_data->data);
free(my_data->data); //先释放数据域的内存
free(my_data); //再释放指向结构体的指针变量
return 0;
}
运行结果
对比上面两个程序,我们能发现:
- 存储大小方面:代码1的结构体占用内存最小,代码2有个指针占用8字节
- 数据连续存储方面:代码1的结构体数据是在连续的存储空间下;而代码2的数据域是单独开辟的空间。
- 释放内存方面:代码1可以直接释放;而代码2是指针的方式,需要先释放数据域部分,才能释放指向结构体的指针变量,否则会内存泄露。