c语言学习之路————动态内存分配(malloc,alloc,realloc)

我们一般了解的内存内部分为三个区:栈区,堆区,静态区

栈区:一版存储的的是局部变量,以及函数的形参,基本数据类型定义的变量

堆区(动态内存分贝的空间):

静态区:全局变量,静态变量(static修饰)

今天我学习的是关于堆区的动态内存分配,我们可以按照自己自己的意愿在堆区上开辟自己需要的内存空间,还可以对我们在对u去开辟的空间进行调整。

小知识点:在C99标准下有一种规定,在定义数组的时候可以在在定义数组大小的时候放入变量来控制我要开辟数组的大小(变长数组)exp:

#include <stdio.h>
int main()
{
   int a = 0;
   scanf("%d",&a);
   int arr[n]={0};
   return 0;
}

而在我们一般的编译器中这这情况是不被允许的,在定义数组的大小时只能用确定的常量数字,const修饰的常变量也不行,因为这种的开辟空间的方式时固定的,不灵活,开辟内存实在编译的时候开始开辟内存的的空间,所以我们需要更加灵活的开辟空间的方式,

涉及到的函数malloc和free

malloc:void* malloc(size_t size)    头文件是<stdlib.h>

开辟动态空间大小为size(byte)

返回值:

当返回空指针(NULL)时,表示堆区每有足够的空间提供,或着开辟失败,这时我们可以用strerror(erron)获取错误信息,再用printf输出打印到控制台面板查看,一般我们运用malloc函数对堆取开辟动态内存的时候都要有这一步检测,避免我们开辟出问题,而不知道问题在哪;如果开辟成功将会返回这段连续空间的起始地址。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <erron.h>
int main()
{
   int* p=(int*)melloc(10*sizeof(int));
//开辟十个整形的动态内存空间,我们希望用整型来维护就用整形指针接受,也可以用别的类型的指针接收,而这 //里需要注意的是既然用整型的指针接受,就要对malloc进行强制类型转换,因为它返回的是void* 型的
   if(p==NULL)
   {
     printf("%s",strerror(erron));
   }
   free(p);
   p=NULL;//每次的动态内存空间使用完记得释放
   return 0;
}

size_t:

一般情况代表unsigned int无符号整数

size:

代表你要在动态区开辟的连续空间的字节数,这里要特别注意的是如果这里的size为0,那么之后的操作在标准中未定义过,接下来的事,将取决于不同的编译器

free函数:void free(void* ptr)            头问件和malloc一样

用来归还或者释放前面申请的动态内存空间,此处的ptr指针只能指向已经申请的动态内存空间的起始地址,释放完空间,还要将这个指针的指向指空(ptr=NULL),不然在下一次引用时容易出错,其实就算我们不对申请的动态内存释放,系统也会在程序结束之后也会归还空间,但不及时,万一在程序结束之前,我们还有其他的操作,为释放的内存会对我们之后的程序产生影响的风险;

如果这里的ptr是空指针,将什么都不做。

calloc:void*calloc(size_t num,size_t size)       头文件同上

与mallloc的区别在于,申请的动态空间的每个元素被初始化为0

size_t num:

要开辟的元素个数,

size_t size:

每个元素的大小

realloc:void* realloc(void* memblock,size_t size)

这个函数在申请动态内存空间上更加灵活,它可以对已申请的动态内存空间调整它的大小,对于临时想要改变动态内存空间大小的需求,但在调整的时候分为两种情况,如果对于要调整的动态内存空间的需求是更大时,这块内存空间之后有足够的空间,他会再原来的基础扩展,返回的地址也还是pte指向的位置;但如果要调整的动态空间的后面的空间不满足它要扩大的需求,系统会重新再堆取开辟一块需求大小的动态内存空间,随之,返回返回指针的位置也不再是ptr,而是新开辟的动态空间的起始位置,

在使用realloc时要注意,需要用另一个指针来接收它的返回值有可能是NULL,exp:

#include <stdio.h>
#include <stdlib.h>
int main()
{
   int* p=(int*)malloc(20);//20个字节五个整形,但我现在想要将0~9打到屏幕上,所以需要再申请五个字 //节
   int i=0;
   for(i;i<5;i++)
   {
      printf("%d",*(p+i));//但我现在想要将0~9打到屏幕上,所以需要再申请五个字节
   }
   //int* p=(int*)realloc(p,40);//这样的写法其实是有危险的,因为如果我们要申请的动态内存空间,出 //现失败的情况,或者,超出了堆区的内存空间,将会返回一个空指针,如果我们将空指针直接赋给p的话,那么 //原本指向0~4的数字数据就会丢失在内存,无法找到,这样风险很大,所以我们建议用第二个指针去接收 //realloc的返回指针
   int* p1=(int*)realloc(p,40);//10个整型
   for(i;i<10;i++)
   {
     printf("%d",*(p1+i));
   }
   free(p);
   p=NULL;//每次的动态内存空间使用完记得释放
   return 0;
}

   

然后还需要p1指针接收的返回值进行检测,就是要对应那种NULL 的情况出现,l

memblock:

已经开辟的动态空间的起始位置

size_t size:

调整之后的动态内存空间的大小(byte)

在最后要提一些注意事项:

就是在每次使用的动态内存的申请之后接收返回值之后,要对返回值进行检测后再,再对空间进行使用还是内存中数据解引用,切记不敢对空指针进行解引用(如果是对指针进行解引用操作是堆内存非法访问)

要注意不要越界访问,就是越出你申请的动态空间去,访问堆区的其他内存空间

free的对象能是堆区开辟的动态内存,不能是栈区的对象,或者别的区的对象,而且必须是开辟动态空间的起始地址,就是不能对指向动态内存的指针进行变动

重复释放同一块空间也会发生错误,一般采用谁申请谁释放,每次释放完之后,再指针置空

动态内存空间不是放会导致内存泄漏,一直会消耗内存

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值