0长数组
https://blog.csdn.net/zhizhengguan/article/details/111472884
零长度数组概念¶
众所周知, GNU/GCC 在标准的 C/C++ 基础上做了有实用性的扩展, 零长度数组(Arrays of Length Zero) 就是其中一个知名的扩展.
多数情况下, 其应用在变长数组中, 其定义如下
首先对 0长度数组, 也叫柔性数组 做一个解释 :
-
用途 : 长度为0的数组的主要用途是为了满足需要变长度的结构体
-
用法:在一个结构体的最后,申明一个长度位0的数组,就可以使得这个结构体是可变长的。
对于编译器来说,此时长度位0的数组不占空间,因为数组名本身不占空间,它只是一个偏移量, 数组名这个符号本身代表了一个不可修改的地址常量
(注意 : 数组名永远都不会是指针!), 但对于这个数组的大小, 我们可以进行动态分配。
注意 :如果结构体是通过calloc、malloc或 者new等动态分配方式生成,在不需要时要释放相应的空间。
- 优点:比起在结构体中声明一个指针变量、再进行动态分 配的办法,这种方法效率要高。因为在访问数组内容时,不需要间接访问,避免了两次访存。
- 在结构体中,数组为0的数组必须在最后声明,使 用上有一定限制。
零长度数组的用途¶
我们设想这样一个场景, 我们在网络通信过程中使用的数据缓冲区, 缓冲区包括一个len字段和data字段, 分别标识数据的长度和传输的数据, 我们常见的有几种设计思路
- 定长数据缓冲区, 设置一个足够大小 MAX_LENGTH 的数据缓冲区
- 设置一个指向实际数据的指针, 每次使用时, 按照数据的长度动态的开辟数据缓冲区的空间.
我们从实际场景中应用的设计来考虑他们的优劣. 主要考虑的有, 缓冲区空间的开辟, 释放和访问.
C++
#include <iostream>
#include <string.h>
using namespace std;
struct Arr0 {
int len;
char *data;
};
struct Arr1 {
uint64_t len;
char data[1];
};
int main() {
cout << "Arr0 size: " << sizeof(Arr0) << endl;
cout << "Arr1 size: " << sizeof(Arr1) << endl;
struct Arr1 *arr1ptr = (struct Arr1*)malloc(sizeof(struct Arr1) + 10);
cout << "arr1ptr size: " << sizeof(*arr1ptr) << endl;
arr1ptr->len = 10;
memcpy(arr1ptr->data, "1234567890", 10);
cout << "data: " << arr1ptr->data << endl;
return 0;
}
Result:
Arr0 size: 16
Arr1 size: 16
arr1ptr size: 16
data: 1234567890
C++
#include <iostream>
#include <string.h>
using namespace std;
struct Arr0 {
int len;
char *data;
};
struct Arr1 {
uint64_t len;
char data[0];
};
int main() {
cout << "Arr0 size: " << sizeof(Arr0) << endl;
cout << "Arr1 size: " << sizeof(Arr1) << endl;
struct Arr1 *arr1ptr = (struct Arr1*)malloc(sizeof(struct Arr1) + 10);
cout << "arr1ptr size: " << sizeof(*arr1ptr) << endl;
arr1ptr->len = 10;
memcpy(arr1ptr->data, "123456789", 10);
cout << "data: " << arr1ptr->data << endl;
return 0;
}
Result:
Arr0 size: 16
Arr1 size: 8
arr1ptr size: 8
data: 123456789
如果使用以下的方式,则data需要单独申请内存,且与struct Arr1不连续。