动态内存管理学不懂,小代老师带你深入理解动态内存管理(下卷
- 柔性数组
- 6.1 柔性数组的特点:
- 6.2 柔性数组的使用
- 7. 总结C/C++中程序内存区域划分
柔性数组
也许你从来没有听说过柔性数组(flexible array)这个概念,但是它确实是存在的。
C99 中,结构中的最后⼀个元素允许是未知⼤⼩的数组,这就叫做『柔性数组』成员。
例如:
struct st_type
{
int i;
int a[0];//柔性数组成员
};
有些编译器会报错⽆法编译可以改成:
struct st_type
{
int i;
int a[];//柔性数组成员
};
6.1 柔性数组的特点:
• 结构中的柔性数组成员前⾯必须⾄少⼀个其他成员。
• sizeof 返回的这种结构⼤⼩不包括柔性数组的内存。
• 包含柔性数组成员的结构⽤malloc ()函数进⾏内存的动态分配,并且分配的内存应该大于结构的大
小,以适应柔性数组的预期⼤⼩。
typedef struct st_type
{
int i;
int a[0];//柔性数组成员
}type_a;
int main()
{
printf("%d\n", sizeof(type_a));//输出的是4
return 0;
}
6.2 柔性数组的使用
#include<stdio.h>
#include<stdlib.h>
typedef struct un
{
int c;
char a;
int arr [0];
}sort;
int main()
{
sort* p = (sort*)malloc(sizeof(sort)+ sizeof(int) * 10);
if (p == NULL)
{
perror(malloc);
return 1;
}
p->a = 'a';
p->c = 100;
for (int i = 0; i < 10; i++)
{
p->arr[i] = i;
}
for (int i = 0; i < 10; i++)
{
printf("%d", p->arr[i]);
}
sort* s = realloc(p, sizeof(sort) + 40 * sizeof(int));
if (s != NULL)
{
p = s;
s = NULL;
}
else
{
return 1;
}
for (int i = 0; i < 40; i++)
{
printf("%d", p->arr[i]);
}
free(p);
p == NULL;
return 0;
}
struct s
{
int a;
int* arr;
};
int mian()
{
struct s* ps = (struct s*) malloc (sizeof(struct s));
if (ps == NULL)
{
perror("malloc");
return 1;
}
int* temp = (int*)malloc(10 * sizeof(int));
if(temp!=NULL)
{
ps->arr = temp;
temp = NULL;
}
else
{
return 1;
}
ps->a = 100;
for (int i = 0; i < 10; i++)
{
ps->arr[i] = i;
}
//调整空间
temp = (int*) realloc (ps->arr ,sizeof(int) * 20);
if (temp != NULL)
{
ps->arr=temp;
temp = NULL;
}
else
{
perror("realloc");
return 1;
}
for (int i = 0; i < 40; i++)
{
printf("%d", ps->arr[i]);
}
free(ps->arr);
ps = NULL;
free(ps->a);
ps->a = NULL;
}
上述 代码1 和 代码2 可以完成同样的功能,但是 ⽅法1 的实现有两个好处:
第⼀个好处是:⽅便内存释放
如果我们的代码是在⼀个给别⼈⽤的函数中,你在⾥⾯做了⼆次内存分配,并把整个结构体返回给⽤
⼾。⽤⼾调⽤free可以释放结构体,但是⽤⼾并不知道这个结构体内的成员也需要free,所以你不能
指望⽤⼾来发现这个事。所以,如果我们把结构体的内存以及其成员要的内存⼀次性分配好了,并返
回给⽤⼾⼀个结构体指针,⽤⼾做⼀次free就可以把所有的内存也给释放掉。
第⼆个好处是:这样有利于访问速度.
连续的内存有益于提⾼访问速度,也有益于减少内存碎⽚。(其实,我个⼈觉得也没多⾼了,反正你
跑不了要⽤做偏移量的加法来寻址)
扩展阅读:
C语言结构体里面的指针和数组
7. 总结C/C++中程序内存区域划分
C/C++程序内存分配的⼏个区域:
- 栈区(stack):在执⾏函数时,函数内局部变量的存储单元都可以在栈上创建,函数执⾏结束时
这些存储单元⾃动被释放。栈内存分配运算内置于处理器的指令集中,效率很⾼,但是分配的内
存容量有限。 栈区主要存放运⾏函数⽽分配的局部变量、函数参数、返回数据、返回地址等。
《函数栈帧的创建和销毁》 - 堆区(heap):⼀般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。分配⽅
式类似于链表。 - 数据段(静态区):(static)存放全局变量、静态数据。程序结束后由系统释放。
- 代码段:存放函数体(类成员函数和全局函数)的⼆进制代码。