1、如何在一个结构体中动态存放动态字符串
在了解柔性数组之前,我们先考虑这个问题,通常我们要想在结构体中存放一个动态长度字符串主要有以下两种方法:
(1)在结构体中定义一个指针,让该指针指向字符串的动态地址空间
(2)定义一个结构体指针,将结构体和字符串链接在一起
以上两种方法都可以实现,但各自有缺点:
- 第一种方法:会造成结构体和字符串分离,此时字符串其实在代码段放着,这样操作起来会比较麻烦。
- 第二种方法:这种方法虽然将结构体和字符串直接链接在一起了,但是实现起来会比较麻烦,需要先为字符串数组malloc(结构体+字符串数组大小)的空间,然后再将这些数据拷贝到结构体指针指向的空间。
那么有没有一种方法,在结构体中预留未知大小空间供我们动态使用呢,柔性数组就是专门解决这类问题的,我们一起来了解一下:
2、什么是柔性数组
所谓柔性数组就是数组大小是待定的数组,也就是数组大小是可变大的。
柔性数组主要有以下几个特点:
(1)C99 中,结构体中的最后一个元素允许是未知大小的数组,这就叫做柔性数组成员,但结构体中的柔性数组成员前面必须至少一个其他成员。
(2)柔性数组成员允许结构体包含一个大小可变的数组。
(3)sizeof求结构体的大小时,返回的内存大小不包括柔性数组的成员
(4)包含柔性数组成员的结构用malloc ()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。
3、柔性数组的定义
我们根据柔性数组的特点可以做如下定义:
typedef struct packet{
int len;
int a[];//柔性数组成员
}packet;
typedef struct packet{
int len;
int a[0];//柔性数组成员
}packet;
这两种方法定义都是正确的,有些编译器可能对后一种方法无法正确编译。
接下来我们用一个小栗子来看看柔性数组到底如何使用的:
typedef struct packet{
int len;
int a[];
}packet;
int main()
{
packet tmp;//定义一个结构体对象
//根据我们需要的大小进行空间开辟
packet *p = (packet*)malloc(sizeof(tmp)+sizeof(int)* 10);
cout << "packet结构体的大小为:" << sizeof(packet) << endl;
for (int i = 0; i < 10; i++)//如果此时柔性数组空间成功开辟,可插入数据
{
p->a[i] = i;
}
for (int i = 0; i < 10; i++)//验证测试用例
cout << p->a[i] << " ";
cout << endl;
system("pause");
return 0;
}
运行结果:
从结果,我们可以看到,该结构体的大小是4个字节,即sizeof(packet)=sizeof(int),并不包含柔性数组的大小。