重点需要知道:

1.为什么存在动态内存分配

2.动态内存函数:malloc free calloc realloc

3.常见的动态内存错误

4.几个经典的笔试题

5.柔性数组


为什么存在动态内存分配

当前我们知道的内存使用方式:

1.创建一个变量 int a=10;//局部变量 放在 栈区  

int g_a=10;//全局变量 放在 静态区

栈区​:局部变量 函数的形式参数

堆区​:动态内存分配

静态区​:全局变量,静态变量,static int a=10;

2.创建一个数组  int arr【10】;局部和全局放的地方和变量一样


假如我们想创建50个学生的数组 此时vs无法在此情况下创建数组,因为不支持括号里面为变量

但是在部分编译器可以,看编译器是否支持c99

c自学day17-动态内存分配_动态内存

所以我们可以用动态内存来开辟空间


我们先了解下动态内存函数

malloc  向内存申请字节 

void* malloc(size_t size); 开辟失败会返回空指针 所以要​做好检查

返回值由自己决定,所以强制类型转换看具体使用

c自学day17-动态内存分配_数组_02

free​和malloc要成对使用

如果不需要这个空间却不释放空间,会一直占用这个空间,会影响到后续进程

c自学day17-动态内存分配_动态内存_03

calloc 会开辟一块空间元素为0

void*calloc(size_t num,size_t size);

calloc会初始化空间,malloc不会初始化,直接打印会是一堆随机数

c自学day17-动态内存分配_数组_04

realloc     

void*realloc(void*memblock,size_t size)

c自学day17-动态内存分配_柔性数组_05

realloc使用的注意事项

使用时会出现两种情况:1.追加的少 会自己在现在的内存后面追加

2.追加的过大,会重新开辟一块空间把值拷贝过去,释放旧的内存区域。此时地址就会发生变化

3.如果非常大,可能会开辟失败。会给予空指针,此时由于赋值给p,追加失败之后原空间也会消失。所以一般用一个新指针来接受值


用一个新变量来接受realloc,追加成功后在赋值给p

c自学day17-动态内存分配_柔性数组_06

最后也要记得释放内存


常见问题

1.忘记判断是否为空指针,万一为空指针解引用会非法

2.对动态开辟内存进行越界访问(关注自己开辟的空间和实际使用空间要一致)

3.对非动态开辟内存使用free释放(比如对正常使用的int a=10;)

4.使用free释放动态开辟内存的一部分

c自学day17-动态内存分配_动态内存_07

因为此时p指向了最后一个元素,没有在指向malloc开创的第一个元素

5.对同一块动态内存多次释放(指free两次,所以free之后赋予空指针可以避免此情况)

6.动态开辟的空间忘记释放(内存泄漏)(指使用了不用之后忘记回收)


寻找下图代码问题

c自学day17-动态内存分配_数组_08

1.运行代码会出现崩溃  2.存在内存泄漏的问题(str以值的形式传递给了p,p是GetMemory的形参,只在函数内部有效,函数返回后,动态内存未释放且无法再找到 会有内存泄漏)

c自学day17-动态内存分配_柔性数组_09

正确形式

c自学day17-动态内存分配_数组_10


寻找问题

c自学day17-动态内存分配_数组_11


返回栈空间地址的问题(数组前加上static,可以保留值)

c自学day17-动态内存分配_柔性数组_12


柔性数组

C99中,结构中的最后一个元素允许是未知大小的数组,这就叫柔性数组成员

c自学day17-动态内存分配_柔性数组_13


第二种写法,在结构体内用指针,就不用使用柔性数组了

c自学day17-动态内存分配_动态内存_14


柔性数组开辟的是连续的一个空间 指针是从一个内存中再指向另一个开辟的空间。

柔性数组只需释放一次空间 而且没有释放顺序 可以减少错误概率、而且malloc使用的次数少一些,内存利用率相对较高。内存是连续的,访问效率更高。