C语言学习笔记——堆区空间申请笔记(二)

C语言学习笔记

堆区空间申请(二)

本文将以堆区空间申请(一)为基础,继续讨论堆区空间的申请与释放及相关函数的应用。

free释放空间

  • 函数的原型:void free(void *memblock);
  • 函数的写法:free(p);free经常是在我们不再需要用到该堆区空间的时候将其进行释放。void表示无返回值,主函数void表示无参数,也就是其他什么都不用管,直接free§就可以了,这里的p表示申请空间的首地址。
  • **注意点:**1、free后的指针,空间就不能再用了,所以一般指针释放后,赋值一个NULL。但是即使把malloc过的p的空间释放了,p的地址也不会变。没有具体指向的指针,或者说所指向空间访问受限的指针,叫野指针,这个东西不能直接使用;
    2、不能重复释放某一个空间,这将导致程序崩溃
    3、不能释放栈区空间
    4、一定要释放头指针。
  • 崩溃常见的有两种,程序运行时的崩溃,一定是某一行代码引起的;运行结束的崩溃,基本上就是内存越界操作了,非常难找,所以一定要细心地使用指针。
  • 使用malloc申请的空间,在系统结束的时候会自动释放,但是还是要使用free,因为在实际使用情况下,服务器不会进行重启,否则会严重影响用户体验,这是软件公司和程序员的大忌。

malloc一维数组

  • 定义方式和栈区数组不同,但是使用完全一样。其实int *p = (int*)malloc(sizeof(int)*5);这样的语句就是在定义一个堆区数组了
  • 需要对数组进行赋值,可以用循环赋值成指定的值,也可以用memset赋值成0.
  • malloc数组可指定任意长度,在任何需要定义时都可以进行操作。因此他也叫动态定义数组,或者动态空间
  • 变(量)长数组写法:
    const int n = 12;
    int a[n];
    int n;
    scanf("%d",&n);
    int a[n];
    这两种都是变长数组的正确写法,但是有一些编译器可能没有引入,其意义是一个能自定义数组长度的变量,这和malloc在堆区空间中申请数组异曲同工

malloc与一维二维数组指针

  • 写法:int (*p)[5] = (int(*)[5])malloc(sizeof(int)*5);注意小括号一定不能丢了,否则就是指针数组了
  • 若要对上述堆区数组中第3项赋值,应使用下列语句*(*p+2) = 3;这里的*p意义和栈区数组中a相同,即可以理解为a[2],公式***(*p+n) = (*p)[n]**
  • 对于二维数组指针:int (*p)[2][3] = (int(*)[2][3])malloc(sizeof(int)*2*3);,这样的语句相当于在栈区中申请如下的数组:
    int a[2][3];
    int(*p1)[2][3] = &a;对其中的数据赋值尽量用方括号的形式,更加容易理解。这一部分的难点还是和指针有关的操作详见指针学习笔记

calloc函数介绍

  • 功能:申请一段数组空间并且自动全部初始化为0
  • 函数原型:void *calloc(size_t num,size_t size);
  • 头文件:<stdlib.h><malloc.h>
  • 用法:int *p = (int*)calloc(3,4)其中3是数组中的数据个数,4是每个数据所占字节数大小

realloc函数介绍

  • 功能:重新分配内存大小
  • 函数原型:void *realloc(void *memblock,size_t size);
  • 头文件:<stdlib.h><malloc.h>
  • 用法:int *p1 = (int*)realloc(p,20);第一个参数是被操作空间的首地址,第二个参数是要分配的大小
  • 这里介绍另一个函数:_msize(p),其返回值是p的字节数大小,可以用作测试realloc的功能
  • 由于realloc一定会申请一段连续的空间,所以如果原来的内存空间不够,则将其转化为内存碎片,并前往其他内存空间申请,也就是说其首地址可能会发生变化;如果申请的空间过大,则返回值NULL

calloc和malloc的选择

  • 使用场景:calloc申请数组比较好用,其他数据结构,比如链表,树,图,一次申请sizeof(节点),这些用malloc更合适,因为calloc是自动清零的。
  • 效率问题:calloc会初始化内存,所以申请的内存数很多的时候,效率会低一点点。毕竟有时候内存不需要初始化,malloc的效率高一些。不过现代电脑的这点效率问题就是微乎其微了。

*的四种作用

  • 声明的时候有*,表示指针变量int *p
  • *+地址,表示地址操作符*p
  • 数字*数字,表示乘法1*2
  • 注释/* */
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lanciberrr

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值