柔性数组
前言:也许你从来没有听说过柔性数组这个概念,但是它确实是存在的。
一.柔性数组
1.柔性数组的定义
- C99中,结构体中的最后一个元素允许是未知大小的数组,这就叫做『柔性数组』。
代码如下:
//在VS中以下两种都支持(其它编译器可以尝试都试试看)
//第一种
struct S
{
int n;
char c;
int arr[];//未知大小的数组 - arr就是柔性数组
};
//第二种
struct S
{
int n;
char c;
int arr[0];//未知大小的数组 - arr就是柔性数组
};
2.柔性数组的特点
- 结构中的柔性数组成员前面必须至少有一个其他成员。
- sizeof返回的这种结构大小不包括柔性数组的内存。
- 包含柔性数组成员的结构体变量用malloc()函数进行内存的动态分配,并且分配的内存应该大于结构体的大小,以适应柔性数组的预期大小。
包含柔性数组成员的结构体大小:
#include<stdio.h>
struct S
{
int n;
int arr[];
};
int main()
{
printf("%zd\n", sizeof(struct S));//4个字节
return 0;
}
3.柔性数组的使用
#include<stdio.h>
#include<stdlib.h>
struct S
{
int n;
int arr[];
};
int main()
{
//开辟空间
struct S* ps = (struct S*)malloc(sizeof(struct S) + 20 * sizeof(int));
if (ps == NULL)
{
perror("malloc");
return 1;
}
//使用这块空间
ps->n = 100;
printf("n=%d\n", ps->n);
int i = 0;
for (i = 0; i < 20; i++)
{
ps->arr[i] = i + 1;
}
printf("调整前的数组arr的元素值:\n");
for (i = 0; i < 20; i++)
{
printf("%d ", ps->arr[i]);
}
printf("\n");
//调整ps指向空间的大小空间
struct S* ptr = (struct S*)realloc(ps, sizeof(struct S) + 40 * sizeof(int));
if (ptr != NULL)
{
ps = ptr;
ptr = NULL;
}
else
{
return 1;
}
//使用调整后的这块空间
for (i = 0; i < 40; i++)
{
ps->arr[i] = i + 21;
}
printf("调整后的数组arr的元素值:\n");
for (i = 0; i < 40; i++)
{
printf("%d ", ps->arr[i]);
}
//释放空间
free(ps);
ps = NULL;
return 0;
}
4.柔性数组的优势
如果要达到柔性数组的效果,也可以使用以下的代码:
#include<stdio.h>
#include<stdlib.h>
struct S
{
int n;
int* arr;
};
int main()
{
//在堆区开辟空间
struct S* ps = (struct S*)malloc(sizeof(struct S));
if (ps == NULL)
{
perror("malloc");
return 1;
}
//开辟指针arr指向的空间
int* temp = (int*)malloc(20 * sizeof(int));
if (temp != NULL)
{
ps->arr = temp;
}
else
{
return 1;
}
//使用空间
ps->n = 100;
printf("n=%d\n", ps->n);
int i = 0;
for (i = 0; i < 20; i++)
{
ps->arr[i] = i + 1;
}
printf("调整前的数组arr的元素值:\n");
for (i = 0; i < 20; i++)
{
printf("%d ", ps->arr[i]);
}
printf("\n");
//调整空间
temp = (int*)realloc(ps->arr, 40 * sizeof(int));
if (temp != NULL)
{
ps->arr = temp;
}
else
{
perror("realloc");
return 1;
}
//使用调整后的这块空间
for (i = 0; i < 40; i++)
{
ps->arr[i] = i + 21;
}
printf("调整后的数组arr的元素值:\n");
for (i = 0; i < 40; i++)
{
printf("%d ", ps->arr[i]);
}
//释放空间(先释放ps->arr再释放ps)
free(ps->arr);
ps->arr = NULL;
free(ps);
ps = NULL;
return 0;
}
柔性数组有两个好处:
- 方便内存释放:如果我们的代码是在一个给别人用的函数中,你在里面做了⼆次内存分配,并把整个结构体返回给用户。用户调用free可以释放结构体,但是用户并不知道这个结构体内的成员也需要free,所以你不能指望用户来发现这个事。如果我们把结构体的内存以及其成员要的内存一次性分配好了,并返回给用户一个结构体指针,用户做一次free就可以把所有的内存也给释放掉。
- 有利于访问速度:连续的内存有益于提高访问速度,也有益于减少内存碎片。
二.总结C/C++中程序内存区域划分
C/C++程序内存分配的几个区域:
- 栈区(stack):在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。栈区主要存放运行函数和分配的局部变量、函数参数、返回数据、返回地址等。《函数栈帧的创建和销毁》
- 堆区(heap):一般由程序员分配释放,若程序员不释放,程序结束时可能由操作系统( Operating System)回收。分配方式类似于链表。
- 数据段(静态区):存放全局变量、静态数据(static)。程序结束后由系统释放。
- 代码段:存放函数体(类成员函数和全局函数)的二进制代码。程序结束后由系统回收。
创作不易,如果能帮到你的话能赏个三连吗?感谢啦!!!
标签:ps,arr,struct,int,C++,内存,数组,柔性 From: https://blog.csdn.net/2203_76003626/article/details/139493032