结构体内长度为0的数组

结构体内长度为0的数组

参考资料

*结构体中数组下标为0
思考一种场景:需要一个结构体,结构体中的需要一个缓冲区,用于接收不定长数据。则最可能想到的就是两种解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//1.开辟定长大缓冲区,用定长数组
#define MaxLength 1024
struct S1
{
int len;//实际数据长度len<MaxLength
int data[MaxLength];
};

int main()
{
int data[10] = { 0,1,2,3,4,5,6,7,8,9 };
int len = 10;
struct S1* pS1;
int data[10] = { 0,1,2,3,4,5,6,7,8,9 };
int len = 10;
if (pS1 = (struct S1*)malloc(sizeof(S1)))
{
pS1->len = len;
memcpy(pS1->data, data,sizeof(pS1->data[0])*len);
}
free(pS1);
pS1 = nullptr;
return 0;
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//结构体里使用指针做缓冲区
struct S2
{
int len;
int* data;
};
int main()
{
int data[10] = { 0,1,2,3,4,5,6,7,8,9 };
int len = 10;
struct S2* pS2;
if (pS2 = (struct S2*)malloc(sizeof(S2)))//一步
{
if (pS2->data = (int*)malloc(sizeof(int) * len))//两部
{
//两次分配的内存是不连续的, 需要分别对其进行管理
memcpy(pS2->data, data, sizeof(int) * len);
}
}
free(pS2->data);
free(pS2);
pS2 = nullptr;
}
  • 使用指针结果作为缓冲区, 只多使用了一个指针大小的空间, 无需使用 一定 长度的数组, 不会造成空间的大量浪费.

  • 但那是开辟空间时, 需要额外开辟数据域的空间, 释放时候也需要显示释放数据域的空间, 但是实际使用过程中, 往往在函数中开辟空间, 然后返回给使用者指向 struct point_buffer 的指针, 这时候我们并不能假定使用者了解我们开辟的细节, 并按照约定的操作释放空间, 因此使用起来多有不便, 甚至造成内存泄漏。

定长数组使用方便, 但是却浪费空间, 指针形式只多使用了一个指针的空间, 不会造成大量空间分浪费, 但是使用起来需要多次分配, 多次释放, 那么有没有一种实现方式能够既不浪费空间, 又使用方便的呢?

GNU C 的0长度数组, 也叫变长数组, 柔性数组就是这样一个扩展. 对于0长数组的这个特点,很容易构造出变成结构体,如缓冲区,数据包等等:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
struct S3
{
int len;
int data[0];
};
int main()
{
int data[10] = { 0,1,2,3,4,5,6,7,8,9 };
int len = 10;
struct S3* pS3;
if (pS3 = (struct S3*)malloc(sizeof(struct S3) + sizeo (int) * len))//len这里不分配也可以memcpy,但free会出问题
{
memcpy(pS3->data, data, sizeof(int) * len);
}
free(pS3);
pS3 = nullptr;
return 0;
}