个人博客网址:https://ljsblog.com

动态内存分配(十)

在不知道所需要的空间大小的情况下,这时就可以使用动态内存开辟。
当开辟的空间不再使用时,用free函数来释放calloc、malloc或realloc所分配的内存空间。

动态内存函数

free函数

free函数是用来释放动态开辟的空间
格式:
void free(void *ptr)
free函数的头文件: stdlib.h

malloc函数

malloc函数会在内存开辟一块连续可用的空间,并返回一个指向它的指针,若开辟失败,则返回NULL,所以malloc的返回值一定要检查。
格式:
void *malloc(size_t size)
头文件: stdlib.h
例:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main()
{int i=0;//向内存申请10个整形空间//因为malloc的返回值的类型是void*,所以需要用(int*)将其转换化为int*类型int* p=(int*)malloc(10*sizeof(int));//检查开辟成功还是失败if(p==NULL)//判断指针是否为空,为空则代表开辟空间失败{//打印错误原因printf("%s\n",strerror(errno));}else{//赋值并打印for(i=0;i<10;i++){*(p+i)=i;}for(i=0;i<10;i++){printf("%d ",*(p+i));//0 1 2 3 4 5 6 7 8 9 }}//释放空间free(p);//此时,虽然空间被释放掉,但p依然指向那个地址,所以需要将p赋一个空指针p=NULL;return 0;
}

calloc函数

calloc函数会在内存开辟一块连续可用的空间,并返回一个指向它的指针。
与malloc的不同是,calloc会把开辟的空间的每个字节初始化为零。
格式
void *calloc(size_t nitems, size_t size)
nitems:元素个数。
size:元素大小。
头文件: stdlib.h
例:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
int main()
{int i=0;int* p=(int*)calloc(10,sizeof(int));//向内存申请10个大小为int的空间并将每个字节初始化为0if(p==NULL){printf("%s\n",strerror(errno));}else{for(i=0;i<10;i++){printf("%d ",*(p+i));//0 0 0 0 0 0 0 0 0 0}}free(p);p=NULL;return 0;
}

realloc函数

realloc函数可以调整动态开辟空间的大小。
使用realloc函数的注意事项:

  1. 原有空间后有足够大的空间,就直接在原有内存后追加空间,原来空间内容不发生变化。
  2. 原有空间后没有足够大的空间,则另找一个合适大小的连续空间来使用,并将原内存的数据移动到新的空间,释放旧的内存,函数返回的将是一个新空间的地址。
  3. 需要用一个新的指针变量来接受realloc函数的返回值。

格式:
void *realloc(void *ptr, size_t size)
ptr:之前开辟的内存块地址
size:调整后新大小
例:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main()
{int i=0;int* p=(int*)malloc(20);//使用malloc开辟了20个字节空间int* p1=NULL;if(p==NULL){printf("%s\n",strerror(errno));}else{for(i=0;i<5;i++){*(p+i)=i;}}//希望有40个字节空间p1=(int*)realloc(p,40);//使用realloc调整内存空间为40个字节if(p1!=NULL){p=p1;for(i=5;i<10;i++){*(p+i)=i;}for(i=0;i<10;i++){printf("%d ",*(p+i));//0 1 2 3 4 5 6 7 8 9}  }//释放内存free(p);p=NULL;return 0;
}

常见的动态内存错误

1.对NULL指针解引用操作
错误示例:

#include <stdio.h>
#include <stdlib.h>
int main()
{int* p=(int*)malloc(40);//有可能malloc开辟空间失败返回的NULL*p=10;return 0;
}

2.对动态开辟空间的越界访问
错误示例:

#include <stdio.h>
#include <stdlib.h>
int main()
{int i=0;int* p=(int*)malloc(10*sizeof(int));//10个intif(p==NULL){return 0;}for(i=0;i<=10;i++)//越界{*(p+i)=i;}free(p);p=NULL;return 0;
}

3.对非动态开辟的内存使用free释放
错误示例:

#include <stdio.h>
#include <stdilb.h>
int main()
{int a=10;int* p=&a;free(p);//对非动态开辟的内存使用free释放p=NULL;return 0;
}

4.使用free函数释放动态开辟内存的一部分
错误示例:

#include <stdio.h>
#include <stdlib.h>
int main()
{int i=0;int* p=(int*)malloc(10*sizeof(int));if(p==NULL){return 0;}for(i=0;i<10;i++){*p++=i;}//p已经不在原来的位置了free(p);p=NULL;return 0;
}

5.对同一块动态内存多次释放
错误示例:

#include <stdio.h>
#include <stdlib.h>
int main()
{int i=0;int* p=(int*)malloc(10*sizeof(int));if(p==NULL){return 0;}free(p);free(p);return 0;
}

6.忘记释放动态开辟内存
错误示例:

#include <stdio.h>
#include <stdlib.h>
int main()
{while(1){malloc(1);}return 0;
}

柔性数组(C99)

在结构体内,结构体中的最后一个元素可以是未知大小的数组,而且有特定的形式[]或者[0],叫做柔型数组成员

  • 结构体中柔性数组成员前面必须至少有一个成员
  • 在计算结构体大小时,不包含柔性数组成员
#include <stdio.h>
#include <stdlib.h>
struct S
{int n;int arr[];
};
int main()
{int i=0;struct S* p=(struct S*)malloc(sizeof(struct S)+5*sizeof(int));struct S* p1=NULL;p->n=1;if(p==NULL){return 0;}for(i=0;i<5;i++){p->arr[i]=i;}p1=(struct S*)realloc(p,44);if(p1!=NULL){p=p1;for(i=5;i<10;i++){p->arr[i]=i;}for(i=0;i<10;i++){printf("%d\n",p->arr[i]);}}free(p);p=NULL;return 0;
}

C语言内存分区

1.栈区(stack)

栈区是一种先进后出的内存结构,由编译器自动分配释放,存放函数的返回值、局部变量、函数参数、返回地址等。

2.堆区(heap)

用于动态内存分配。一般由程序员分配释放,若程序员不释放,程序结束时由操作系统回收。

3.数据段(静态区)(static)

存放全局变量,静态数据,程序结束时由操作系统释放。

4.代码段

存放函数体的二进制代码。

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

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

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

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

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

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

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

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

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

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

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

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

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

  7. C语言动态内存分配函数

    目录 1.malloc() 2.free() 3.calloc() 4.realloc() 5.小结 在C中我们开辟内存空间有两种方式 : 1.静态开辟内存 : 例如: int a; int b[10 ...

  8. C语言-动态内存分配总结

    目录 1 malloc 2 calloc 区别联系 3 memset 4 realloc 1 malloc void *malloc( unsigned int num_bytes) 分配长度为num ...

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

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

  10. 不允许指针指向不完整的类类型_8.7 C语言动态内存分配与指向它的指针变量

    01什么是内存的动态分配 1.全局变量是分配在内存中的静态存储区的,非静态的局部变量(包括形参)是分配在内存中的动态存储区的,这个存储区是一个"栈"的区域. 2.C语言允许建立内存 ...

最新文章

  1. Qt中文手册 之 QTreeWidget
  2. c枚举类型enum例题_一篇文章让你详细了解Java中Enum枚举类的使用
  3. vue-router 去掉#
  4. Boost Asio总结(16)例子
  5. CG CTF WEB AAencode
  6. lisp求面与面的差集_AcGeVector3d是点阵的集合,通过等分点的差集得到。 新的点可以通过点与点阵相差得......
  7. 总账分录追溯发票或者付款
  8. Mybatis 拦截器介绍
  9. (转)postgis常用函数介绍(二)
  10. java遍历日期_Java遍历起止日期中间的所有日期操作
  11. 阿里面试回答的认真总结
  12. textfield tips
  13. 大学生创业计划书PPT模板在哪免费下?经典商业计划书PPT模板大全
  14. 106个计算机学部毕业设计项目大全(附源码)
  15. 开放源代码不得不知的一些事情
  16. H5加壳APP发布Android、IOS应用(证书响应文件制作)
  17. 物联网中常用到的DTU到底是什么?
  18. 五大赛场十大赛题百万奖金!山东省第二届数据应用创新创业大赛等你来!
  19. L1-005. 考试座位号
  20. 题目20: 吝啬的国度

热门文章

  1. 案例3-1 基于控制台的购书系统
  2. js-排序-对象key自动排序问题
  3. 天天在做大数据,你的时间都花在哪了
  4. dpdk中文-DPDK学习路线图
  5. STC单片机获取红外解码从串口输出
  6. 注册中心Consul
  7. 字节跳动二号人物——山西人张利东
  8. python将列表中的偶数变成平方、奇数不变_编写程序,将列表s=[9,7,8,3,2,1,5,6]中的偶数变成它的平方,奇数保持不变,运行效果如书上图所示。_学小易找答案...
  9. m4s格式转换mp3_超级详细!如何将B站缓存m4s文件无损转换为mp4格式
  10. 十三.人脸检测和车牌识别