28.0、C语言——柔性数组
柔性数组:
? ? ? ? 也许你从来没有听说过 柔性数组(flexible array)这个概念,但是它确实是存在的;C99中,结构中的最后一个元素允许时位置大小的数组,这就叫做【柔性数组】成员;
柔型数组的特点 ->
????????- 结构中的柔性数组成员前面?必须至少有一个?其他成员; ? ? ? ? - sizeof 返回的这种结构大小不包括柔性数组的内存; ? ? ? ? - 包含柔性数组成员的结构用 malloc() 函数进行内存的动态分配,并且分配的内存应该大于结构体的大小,以适应柔性数组的预期大小;
两种定义方式【使用的编译器不支持的话,就换一种定义方式】:?
struct S {
int i;
int arr[];
}
struct S2 {
int i;
int arr2[0];
}
????????当我们查看该结构体占用的内存时,发现在结构体中柔型数组不占用内存,结构体的大小仅仅是除去柔型数组外其他元素的大小; ? ? ? ? 【形式一】这是因为柔型数组在定义时未被赋予任何的内存空间,那么我们可以动态的赋予 柔性数组 内存空间的大小 ,代码如下所示:
typedef struct S {
int i;
int arr[];
}S;
int main() {
S* ps = malloc(sizeof(S)+sizeof(int)*5);
free(ps);
ps = NULL;
return 0;
}
????????这里相当于是先申请了一块结构体?S 大小的空间,然后又申请了20个字节的空间给 arr 柔性数组;
如果之后觉得分配的数组空间不够用了,那么可以用 realloc 函数动态扩增 arr 柔型数组;
int main() {
S* ps = malloc(sizeof(S)+sizeof(int)*5);
S* tmp = (S*)realoc(ps,44);
if (tmp != NULL) {
ps = tmp;
}
free(ps);
ps = NULL;
free(tmp);
tmp = NULL;
return 0;
}
?
【形式二】接下来我们写一段不用柔型数组,但是也可以实现和柔型数组相同效果的代码; 如下所示:
typedef struct S {
int i;
int* arr;
}S;
int main() {
S* ps = (S*)malloc(sizeof(S));
ps->arr = (int*)malloc(sizeof(int) * 5);
free(ps);
ps = NULL;
free(ps->arr;
ps->arr = NULL;
return 0;
}
? ? ? ? 1. 定义了一个结构体 S ,该结构体中有两个元素一个是 整型变量 i ,第二个是整型指针 arr; ? ? ? ? 2.?在 main 函数中首先用 malloc 函数动态开辟了一块结构体 S 大小的空间,并让指针 ps 去管理这块动态开辟出来的内存空间;? ? ? ? ? 3. 然后再次动态开辟了一块 5 个整型字节大小内存空间,并让 ps 管理的那块结构体 S 空间中的 arr 整型指针去管理这块 5个整型字节的内存空间;
????????那么学到这的时候,我有一些疑惑 ->
????????就是虽然我们开辟了一块 结构体 S 大小的内存空间,返回的指针也强转为 S* 类型,但是内存空间中怎么就自动将结构体 S 中的成员变量放进这块内存空间了呢?
????????这里只是开辟一块空间,但是并不知道这块空间中应该存放什么; ????????在这里我的个人理解是 S* ps 定义了一个结构体 S 类型的指针 ps ,那么这个指针 ps 存放的就是 结构体 S 的一个对象的地址,而这个指针 ps 又同时管理这块开辟的空间,所以这个 S 的对象就和这块空间产生了联系,那么就上述这段代码来说,在这块空间中就将一部分内存分给了结构体 S 对象中的变量 i 一部分分给了指针 arr;
????????既然不用柔性数组也能达到柔型数组的效果,那柔性数组还有什么存在的必要呢? 接下来我们看看柔性数组的优势 ->
【形式一】
? ? ? ? 1. 只开辟一块连续的动态内存空间,释放的时候也只需要 free() 一次,降低代码的出错率; ????????2. 开辟的内存空间是连续的,这样内存访问的效率会更高;?
【形式二】
? ? ? ? 1. 更容易出错,因为他用了两次 malloc() 函数,释放时也需要两次 free() 而且释放的顺序也不能出错; ? ? ? ? 2. malloc() 函数每次使用开辟的空间位置都是随机的,哪有空间就在哪开辟;开辟过后有些地方的内存有可能会变成剩下的不多不少的一个内存境地【这些内存就被称作为内存碎片,就不能很好的被利用】,就浪费了; ? ? ? ? 3. 由于两次 malloc() 函数开辟的动态内存空间不是连续的,所以访问效率会较低;
? ? ? ?
|