目录

1.malloc()
2.free()
3.calloc()
4.realloc()
5.小结


在C中我们开辟内存空间有两种方式 :
1.静态开辟内存 : 例如:

int a;
int b[10];

这种开辟内存空间的特点是
所开辟的内存是在栈中开辟的固定大小的 ,如a是4字节 ,数组b是40字节 ,并且数组在申明时必须指定其长度 , 如果是全局数组的话,内存是在编译时分配好的,如果是局部变量数组的话,运行时在栈上静态分配内存。不管是全局数组还是局部数组,它们都有一个特点,那就是数组大小是确定的,是代码中写死的。那如果我们想在程序运行时才确定一个数组的大小 , 前两种在栈上分配内存的方法显然是不行的 , 举个例子 :

int n;
scanf("%d", &n);
int a[n];

这样编写会在编译时出错 , 编译器会提醒[ ]中应为常量表达式 , 在C中定义数组时可以用的有以下几种 ,例:

#define N 10
enum NUM{M=10
};
int a1[N];
int a2[10];
int a3[M];

需要注意的是 ,C中const int n =10 ; n并不能作为数组长度定义数组 , 但C++中则可以 , 
但我们对于开辟空间的需求 , 往往不限于此 , 最常见的定义数组时数组大小在程序运行时才知道的 , 静态开辟就已经无能为力 . 当然有静态开辟 ,肯定也有动态开辟 ,接下来我们就来看动态开辟内存空间

2.动态开辟内存 :
在C中动态开辟空间需要用到三个函数 :
malloc(), calloc(), realloc() ,这三个函数都是向堆中申请的内存空间.
在堆中申请的内存空间不会像在栈中存储的局部变量一样 ,函数调用完会自动释放内存 , 需要我们手动释放 ,就需要free()函数来完成.
下面让我们来看看这几个函数各自的特点, 用法, 区别, 联系.

1.malloc()

void * malloc(size_t size)

1).malloc()函数会向堆中申请一片连续的可用内存空间
2).若申请成功 ,,返回指向这片内存空间的指针 ,若失败 ,则会返回NULL, 所以我们在用malloc()函数开辟动态内存之后, 一定要判断函数返回值是否为NULL.
3).返回值的类型为void*型, malloc()函数并不知道连续开辟的size个字节是存储什么类型数据的 ,所以需要我们自行决定 ,方法是在malloc()前加强制转 ,转化成我们所需类型 ,如: (int*)malloc(sizeof(int)*n).
4).如果size为0, 此行为是未定义的, 会发生未知错误, 取决于编译器

具体怎么用呢 ,举个例子 .

int *p = NULL;
int n = 0;
scanf("%d", &n);
p = (int*)malloc(sizeof(int) * n);
if(p != NULL){//....需要进行的操作
}

这时就相当于创建了一个数组 p[n] ,这个n的值并不需要像定义一个普通数组一样必须是常量, 可以使程序运行时得出的, 或是用户输入的


2.free()

void free(void* ptr)
在堆中申请的内存空间不会像在栈中存储的局部变量一样 ,函数调用完会自动释放内存 , 如果我们不手动释放, 直到程序运行结束才会释放, 这样就可能会造成内存泄漏, 即堆中这片内存中的数据已经不再使用, 但它一直占着这片空间, (通俗说就是就是占着茅坑不拉屎), 所以当我们申请的动态内存不再使用时 ,一定要及时释放 .

1).如果ptr没有指向使用动态内存分配函数分配的内存空间,则会导致未定义的行为。
2).如果ptr是空指针,则该函数不执行任何操作。
3).此函数不会更改ptr本身的值,因此它仍指向相同(现在已经无效)的位置(内存)
4).在free()函数之后需要将ptr再置空 ,即ptr = NULL;如果不将ptr置空的话 ,后面程序如果再通过ptr会访问到已经释放过无效的或者已经被回收再利用的内存, 为保证程序的健壮性, 一般我们都要写ptr = NULL; .

注意 : free()不能重复释放一块内存, 如:

free(ptr);
free(ptr);

是错的, 已经释放过的内存不能重复释放, 会出现内存错误 .

free()具体用法, 举个例子 :

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

3.calloc()

void * calloc(size_t num,size_t size)
与malloc()函数的区别只在于, calloc()函数会在返回地址之前将所申请的内存空间中的每个字节都初始化为0 .

1).calloc()函数功能是动态分配num个大小(字节长度)为size的内存空间 .
2).若申请成功 ,,返回指向这片内存空间的指针 ,若失败 ,则会返回NULL, 所以我们在用calloc()函数开辟动态内存之后, 一定要判断函数返回值是否为NULL.
3).返回值的类型为void*型, calloc()函数虽然分配num个size大小的内存空间 ,但还是不知道存储的什么类型数据 ,所以需要我们自行决定 ,方法是在calloc()前加强制转 ,转化成我们所需类型 ,如: (int*)calloc(num, sizeof(int)).
4).如果size与num有一个或都为0, 此行为是未定义的, 会发生未知错误, 取决于编译器

所以如何我们对申请的内存空间的内容要求初始化,那么可以很方便的使用calloc函数来完成这个需求。
例如 :


4.realloc()

void * realloc(void * ptr,size_t size)

realloc()函数让动态内存管理更加灵活 .在程序运行过程中动态分配内存大小,  如果分配的太大 ,则浪费空间, 如果太小, 可能还是会出现不够用的情况 .为了合理的利用内存,我们一定会对内存的大小做灵活的调整。那realloc() 函数就可以做到对动态开辟内存大小的调整(既可以往大调整, 也可以往小了调整) .

1).ptr为需要调整的内存地址
2).size为调整后需要的大小(字节数)
3).若调整成功, 返回值为调整大小后内存的起始位置(也就是指向调整后内存的指针), 若失败(当没有内存可以分配时, 一般不会出现), 则返回NULL, 所以还是要对返回值判空
4).如果ptr是空指针, 则和malloc()函数一样作用一样

注意 : realloc()函数在扩大内存空间时有两种情况
1).ptr所指的内存后有足够的内存空间用来扩展 ,如图 :

2).ptr所指内存后没有足够的空间来扩展 ,如图 :
 

当第二种情况时, 若申请新的内存空间成功, 会将ptr所指向的内存中的内容拷贝到新的内存空间中, ptr所指向的内存会被释放, 返回新得内存地址, 若不成功 ,ptr 所指内存不会被释放, 函数返回NULL


5.小结

1).malloc()和calloc()函数用法一样, 唯一的区别是calloc()会对所申请内存的每个字节初始化为0

2).malloc(), calloc(), realloc()申请的内存不再使用时 ,一定要用free()释放 ,否则会造成内存泄漏

3).p = realloc(ptr, size)函数返回值不为空时, 释放内存时不需写free(ptr) ,只需写free(p)

C语言动态内存分配函数相关推荐

  1. C语言动态内存管理和动态内存分配函数

    给变量分配内存空间可分为静态内存分配和动态内存分配. 静态内存分配属于编译时给变量分配的空间,动态分配属于在程序运行时给变量分配的空间 静态分配属于栈分配,动态分配属于堆分配 运行效率上,静态内存比动 ...

  2. c语言动态内存分配数组,【C】动态内存分配

    ## 动态内存分配的意义 C语言中的一切操作都是基于内存的 变量和数组都是内存的别名 内存分配由编译器在编译期间决定 定义数组的时候必须指定数组长度 数组长度是在编译期就必须确定的需求: 程序在运行过 ...

  3. linux 在指定区域分配内存 c语言,C语言动态内存分配:(一)malloc/free的实现及malloc实际分配/释放的内存...

    一.malloc/free概述 malloc是在C语言中用于在程序运行时在堆中进行动态内存分配的库函数.free是进行内存释放的库函数. 1.函数原型 #include void *malloc( s ...

  4. C语言动态内存分配:(一)malloc/free的实现及malloc实际分配/释放的内存

    最新个人博客 shankusu.me 以下内容转载或参考或引用自 https://blog.csdn.net/zxx910509/article/details/62881131 一.malloc/f ...

  5. C语言动态内存分配详解

    文章目录 前言 一.为什么存在动态内存分配 1.已掌握的内存开辟方式 2.上述开辟空间方式的特点 3.为什么存在动态内存分配 二.动态内存函数的介绍 1.malloc 2.free 3.calloc ...

  6. C语言:动态内存分配+经典面试题

    前言: 通常,我们在栈空间开辟的内存都是固定的,这是十分不方便使用的.为了更加灵活的分配和使用内存,我们要学习C语言中一些常用的与内存分配相关联的函数.顺便,我们会补充数组中柔性数组的知识. 内存分区 ...

  7. 浅谈C语言动态内存分配及柔性数组

    文章目录 前言 1.动态内存的简单介绍 1.动态内存分配是什么? 2.为什么存在动态内存分配? 3.动态内存分配具体方法 1.动态内存函数 2.动态内存注意事项 2.经典面试题分析 3.C/C++程序 ...

  8. c语言释放内存函数,【C语言】内存分配函数malloc/ calloc/ realloc及内存释放free

    前言: 内存区域划分与分配: 1.栈区(stack)--程序运行时由编译器自动分配,存放函数的参数值,局部变量的值等,程序结束时由编译器自动释放. 2.堆区(heap) -- 在内存开辟另一块存储区域 ...

  9. C语言——动态内存分配

    内存分配函数: malloc函数--分配内存块,但是不对其进行初始化. calloc函数--分配内存块,并且对其进行初始化(清0). realloc函数--调整先前分配的内存块大小. 函数原型: vo ...

最新文章

  1. SD-WAN是怎样简化企业网络和节省资金的?
  2. js 为false的几种情况
  3. kindeditor编辑器使用七牛云上传图片
  4. fatal error C1010: 在查找预编译头时遇到意外的文件结尾。是否忘记了向源中添加“#include stdafx.h”?
  5. ZXing二维码和条形码
  6. mybatis入门(七)之日志
  7. glide加载图片闪烁_html5 canvas绘制图片
  8. URL 中,查询字符串与HTML实体冲突,可能带来的问题.
  9. 将项目发布到Git@OSC
  10. python微博评论爬虫_详解用python写网络爬虫-爬取新浪微博评论
  11. 拼音加加符号编码列表
  12. android 指纹 分发,移动终端及基于指纹识别来实现操作的方法和系统与流程
  13. CRMEB 商城分销功能
  14. kubernetes之volumes使用
  15. 怎么做好宝贝标题优化?
  16. 全量备份,差量备份,增量备份的异同
  17. txt文件-英汉字典
  18. 2019/12/25 学习总结(待填坑)
  19. 【九章算法】-动态规划
  20. 基于ArcGIS的遥感影像批量裁剪

热门文章

  1. Ubuntu虚拟机安装VMware Tools
  2. UE5接入在线直播视频源,如hls(m3u8)格式
  3. 基于cubemx的OLED显示+程序下载+代码+步骤+详解
  4. 多进程多线程 ---- Python和Java
  5. Jquery中ul li循环取值方式
  6. 【Flutter从入门到实战】 ⑧、FlexWidget、Flex的主轴和交叉轴、Row和Column的使用、Expanded的FlexFit和flex的使用、Stack、Positioned的使用
  7. Starlink的发展
  8. I Squared Capital将与Rubis就欧洲领先的石油产品、化学品、农产品和化肥存储公司Rubis Terminal开展合作
  9. PowerDesigner---数据库设计软件的介绍与使用
  10. HTTP到底是什么?