柔性数组(flexible array)是结构体终的最后的一个数组,该数组中最后的一个元素是允许未知大小的。
下面是柔性数组的一个申请:
struct J
{
int a;
int arr[];//柔性数组
}p;
int main()
{
printf("当前结构体大小为:%d",sizeof(struct J));
return 0;
}
以下为打印结果:
可以看出对结构体打印的结果是整型变量a的大小,说明该数组还未申请到内存空间。接下来再看看这个代码:
#include<stdio.h>
#include<stdlib.h>
struct J
{
int a;
int arr[];
};
int main()
{
struct J* p = (struct J*)malloc(sizeof(struct J)+5*sizeof(int));
if (p == NULL)
{
printf("分派配失败");
return 1;
}
p->a = 10;
for(int i=0;i<5;i++)
{
p->arr[i] = i + 1;
}
//
//
//
free(p);//操作后释放内存还给操作系统
p = NULL;
return 0;
}
先申请到的新空间结存放在构体指针变量中,因为malloc函数可能存在分配失败的情况,即返回NULL值,于是我们可以在此做判断如果分配失败,则提前结束运行,但如果申请成功就对结构体内部元素进行一些赋值运算。
而对数组进行一些列操作之后,就需要使用free函数对其内存进行释放,而释放过后就需要将其变为空指针,避免编程野指针。
如果在写代码过程中柔性数组的空间可能不满足我们需要,那我们就可以对柔性数组进行内存的调整,那就需要realloc函数。
#include<stdio.h>
#include<stdlib.h>
struct J
{
int a;
int arr[];
};
int main()
{
struct J* p = (struct J*)malloc(sizeof(struct J)+5*sizeof(int));
if (p == NULL)
{
printf("分派配失败");
return 1;
}
p->a = 10;
for(int i=0;i<5;i++)
{
p->arr[i] = i + 1;
}
struct J* sp =(struct J*) realloc(p,sizeof(struct J)+10*sizeof(int));
if (sp == NULL)
return 1;
else
p = sp;
//以下为修改内存后的操作
//.......
//.....
//
free(p);//操作后释放内存还给操作系统
p = NULL;
return 0;
}
在这里可以看到,使用了一个新的结构体类型指针,进行接收新调整的内存,再将其赋值给原来的指针变量,这样就完成了对指针变量的内存调整,同样的也需要对其进行判断之后再进行操作。
之后就可以一系列操作。
当然可以用另一种方式,将数组变为一个数组指针,这样可以进行更灵活的操作:
#include<stdio.h>
#include<stdlib.h>
struct H
{
int a;
int* arr;
};
//为指针arr申请一块数组空间使arr指向这里
int main()
{
struct H* p = malloc(sizeof(struct H) + 5 * sizeof(int));
if (p == NULL)
{
printf("分配未成功\n");
return 1;
}
p->a = 100;
p->arr = (int*)malloc(10 * sizeof(int));
if (p->arr == NULL)
return 1;
for(int i =0;i<5;i++)
{
p->arr[i] = i + 1;
}
struct H* ret = realloc(p->arr, sizeof(int) * 10);//使用内存函数调整数组空间大小
if (ret!=NULL)
p->arr = ret;
//接下来就是使用这块内存
//.....
//......
//接下来就释放
free(p->arr);
free(p);
p = NULL;
return 0;
}
中间进行同样的操作,但是在最后的释放内存的时候,需要先释放数组指针所指向的内存,然后再释放结构体指针p的指向的内存。arr在内部需要先释放,不然要报错。
前者使用数组相比后者使用指针会稍微更好一点,因为后者的代码中多调用了一次malloc函数,会对占用一定内存。
以上就是目前我对柔性数组的学习理解,欢迎大家指正。