【什么?你说你还没学会动态内存】

一、为什么要有动态内存?(绝不是随随便)

内存分配有两种方式:静态分配和动态分配。
静态分配
1)在程序编译或运行过程中,按事先规定大小分配内存空间。
2)必须事先知道所需空间的大小。
3)分配在栈区或全局变量区,一般以数组的形式。
4) 按计划分配
动态分配
1)在程序运行过程中,根据需要大小自由分配所需空间。
2)按需分配
举个例子
我们在定义数组时,长度往往是预先给定的,在整个程序中固定不变。

int a;
int b[10];//数组的长度固定了,只能是10个

所开辟的内存是在栈中开辟的固定大小的,如a是4字节,数组b是40字节,并且数组在申明时必须指定其长度 。如果是全局数组的话,内存是在编译时分配好的,如果是局部变量数组的话,运行时在栈上静态分配内存。不管是全局数组还是局部数组,它们都有一个特点,那就是数组大小是确定的,不管你使用了多少。
但是在实际的编程中, 往往会发生这种情况,想在程序运行时才确定一个数组的大小,即所需的内存空间取决于实际输入的数据 ,而无法预先确定

int b[10];
int b[20];//不能重新指定大小

那么如何解决上述问题? C语言提供了一些内存管理函数 ,这些内存管理函数可以按需要动态的分配内存空间,不需要时也可以把这一块空间回收,等待系统的下次分配。

二、动态分配内存函数(程序员必备基操)

在C中动态开辟空间需要用到三个函数 :
malloc(), calloc(), realloc() ,这三个函数都是向堆中申请的内存空间。
在堆中申请的内存空间不会像在栈中存储的局部变量一样,函数调用完会自动释放内存 , 需要我们手动释放,就需要free()函数来完成。

1、malloc 函数

头文件:#include<stdlib.h>
函数原型: void *malloc(unsigned int size);
功能说明:
在内存的动态存储区 ( 堆区 ) 中分配 一块长度为 size 字节的连续区域 ,用来存放类型说明符指定的类型
函数原型返回 void* 指针,使用时必须做相应的强制类型转换 ,分配的内存空间内容不确定,一般使用memset 初始化
返回值: 分配空间的起始地址 ( 分配成功 )、NULL( 分配失败 )
注意:
1)在调用 malloc 之后,一定要判断一下是否为空,申请内存成功之后再使用。
2)如果多次malloc 申请的内存,第 1 次和第 2 次申请的内存不一定是连续的,不同编译器有不同的特点。

int *p = NULL;
int n = 0;
scanf("%d", &n);
p = (int*)malloc(sizeof(int) * n);
if(p != NULL){
    //....使用操作
}

申请了存放n个int类型数据的内存空间,并且用指针p指向其首地址。如果申请成功,即指针空不为空,那就可以使用。

2、 calloc 函数

头文件: #include<stdlib.h>
函数定义: void * calloc(size_t nmemb,size_t size);
size_t 是无符号整型,它是在头文件中,用 typedef 定义出来的。
函数的功能:在内存的堆中,申请 nmemb 个内存块,每块的大小为 size 个字节的连续区域
函数的返回值:
返回申请的内存的首地址(申请成功)
返回 NULL (申请失败)
注意:malloc 和 calloc 函数都是用来申请内存的
区别:

  1. 函数的名字不一样
  2. 参数的个数不一样
  3. malloc 申请的内存,内存中存放的内容是随机的,不确定的,而 calloc 函数申请的内存中的内容为 0,会自动初始化

3、 free 函数

头文件: #include<stdlib.h>
函数定义 :void free(void *ptr);
函数说明:free函数释放ptr指向的内存。
注意:ptr指向的内存必须是malloc、calloc、relloc动态申请的内存

int *p = NULL;
int n = 0;
scanf("%d", &n);
p = (int*)malloc(sizeof(int) * n);
free(p);
free(p);

是错的,已经释放过的内存不能重复释放,会出现内存错误。
正确用法是:

int *p = NULL;
int n = 0;
scanf("%d", &n);
p = (int*)malloc(sizeof(int) * n);
if(p != NULL){
    //....需要进行的操作
}
//操作完成 ,不再使用这片内存空间
free(p);
p = NULL;

为了确保后面过程误用了指针p,所以在free释放了p之后,还需要让其指向NULL。

4、realloc 函数

动态内存的精华所在这里,当我们使用 malloc 或 calloc 申请了一块内存,使用一段时间之后发现不够用或者内存分配太多了,就可以在原先基础上重新指定分配一块内存下来。
头文件:#include<stdlib.h>
函数的定义: void* realloc(void *s,unsigned int newsize);
函数的功能:在原先 s 指向的内存基础上重新申请内存,新的内存的大小为 new_size 个字节
如果原先内存后面有足够大的空间,就追加,如果后边的内存不够用,则 relloc 函数会在堆区 找一个 newsize 个字节大小的内存申请,将原先内存中的内容拷贝过来,然后释放原先的内存,最后返回新内存的地址。
如果 newsize 比原先的内存小,则会释放原先内存的后面的存储空间,只留前面的 newsize 个字节
返回值:新申请的内存的首地址。

三、内存泄漏(程序员大忌)

什么是内存泄漏?

顾名思义,就是系统中的内存泄漏了,我们不能正确地使用这一块地内存,也就是说:出现了内存的浪费,不能正确使用这一块内存
为啥会用不上?因为内存是靠指针来使用的,当这块指针出现了错误或者找不到了的时候,我们就不能再使用其指向的内存。
当我们使用动态内存空间之后,却忘记了释放,那么这一块内存就不能被系统回收,一直占用着,导致了内存的浪费。
所以,作为一名程序员,一定要把free记心中。

四、总结

常见的动态内存使用错误

1)对NULL指针的解引用操作
在使用malloc、calloc、realloc申请内存之后,要对其返回值判断是否为空。
2)对动态开辟内存空间的越界访问
申请动态内存之后,其也是有大小的,越界访问会出现问题。
3)使用free函数释放一块动态内存的一部分
free函数释放内存时,要从内存的起始位置开始释放。
4)对非动态开辟内存使用free函数释放
free函数只能针对动态申请的内存空间。
5)对同一块动态内存多次释放
6)动态内存空间忘记释放(内存泄漏)

  • 13
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值