C语言:内存动态管理函数

本文介绍了C语言中的动态内存分配机制,包括malloc、calloc、free和realloc函数的用法、返回值处理以及它们之间的差异。重点强调了动态内存使用完毕后的释放和内存空间的调整策略。
摘要由CSDN通过智能技术生成

1.为什么要动态内存分配:

以前我们开辟内存空间的方式:

int n=10;//在栈上开辟4个字节大小的空间
int arr[10]={0};//在栈上开辟40个字节大小的空间

 上述开辟空间的方式有两个特点:

1.所开辟的空间大小是固定的

2.数组在开辟内存空间时,必须要指明数组长度,数组空间一旦确定便不能改变大小。

但有时候对空间的需求,并不仅仅是上述的情况。有时我们需要的空间的大小要在程序运行时才知道,所以数组编译时所开辟的空间的方式就不能满足。

C语言引入动态内存分配,让程序员自己可以申请和释放空间,更加灵活。

 2.malloc函数:

函数原型:

void* malloc(size_t size);// size单位是字节

malloc在内存中申请一块size大小的内存空间,并返回指向这块空间的指针。 

1.如果malloc成功开辟了一块内存空间,那就会返回指向这块空间的起始地址。

2.如果malloc开辟空间失败,就会返回NULL,所以我们要对malloc返回要做检查,避免成为野指针。

#include<stdio.h>
int main()
{
    int* p=(int*)malloc(5*sizeof(int));//开辟一块20字节的内存,并用来存放整型数据
    if(p!=NULL)//要进行检查,不为NULL才使用
      {
        *p=20;
      }
}

3.因为返回类型是void*,所以malloc并不知道所开辟空间的类型,使用的时候需要使用者自己决定。

4.如果size为0,malloc的标准就是未定义的,要取决于编译器。

3.calloc函数:

calloc函数也是用来动态内存分配的,calloc原型:

void* calloc(size_t n,size_t size);

1.n代表个数size代表字节大小意思在内存中分配n个长度为size的连续内存空间。 

2.如果calloc成功开辟了一块内存空间,就会返回指向这一块空间的起始地址。

3.开辟失败,就会返回NULL,所以最好也要进行检查后才使用。

4.calloc还会将所开辟的空间全部初始化为0malloc开辟的内容是随机的。可以根据自身需求进行选择使用。

#include<stdio.h>
int main()
{
	int* p = (int*)calloc(5, sizeof(int));//p是calloc开辟的
	int* ptr = (int*)malloc(sizeof(int) * 5);//ptr是malloc开辟的
	if (p != NULL&&ptr!=NULL)
	{
		printf("calloc:");
       for (int i = 0; i <= 4; i++)
	   {
		  printf("%d ", p[i]);
	   }
		printf("\nmalloc:");
	   for (int i = 0; i <= 4; i++)
	   {
		   printf("%d ", ptr[i]);
	   }
	   return 0;
	}
	else
	{
		perror("p");
		return 1;
	}
}

上面代码,calloc和malloc开辟的空间大小一样,且都是整型类型。 

运行结果:

所以当我们需要对内存空间内容初始化时就可以用calloc函数。

 4.free函数:

我们使用malloc,calloc和realloc这些函数开辟一块内存空间,当我们使用完这块内存空间并不再使用时,我们要及时将这块空间归还操作系统,以免酿下大错。而free就是专门做动态内存的释放和回收的。

free原型:

void free(void* ptr);

1.free无返回值,ptr是调用malloc,calloc和realloc函数开辟内存空间时返回的起始地址(指针)。

2.free只能释放动态开辟的空间,如果free释放的空间是非动态开辟,那free函数的行为是未定义的。

3.如果ptr是NULL,则free函数什么都不做。

#include<stdio.h>
int main()
{
    int* p=(int*)malloc(5*sizeof(int));//开辟一块20字节的内存,并用来存放整型数据
    if(p!=NULL)//要进行检查,不为NULL才使用
      {
        *p=20;
        free(p);//使用完动态内存后,释放内存
        p=NUll;
      }
}

 在上面代码中,在释放后动态内存空间后,此时p中的地址还是指向开辟内存空间的地址,但这个内存空间不属于p了,已经归还给操作系统了,所以如果再使用p就会形成野指针,所以最好就把p置为NULL。

5.realloc函数:

有了realloc函数,能使动态内存管理更为灵活。有时候我们发现我们开辟的动态内存空间偏大或偏小,为了合理使用内存,就要对内存大小进行调整。realloc函数就可以对动态开辟的内存大小进行灵活调节(reallo可以扩大或缩小内存空间)

realloc原型:

void* realloc(void* ptr,size_t size);

void*ptr:需要调正内存大小的地址。

size_t size:需要开辟内存的大小(单位字节)

返回值:调整之后的内存空间的起始地址。

在realloc函数在调节动态内存空间时会有两种情况:

#include<stdio.h>
int main()
{
    int* p=(int*)malloc(sizeof(int)*5);
    if(p==NULL)//检查空间是否开辟成功
       {
         return 1;
       }
    else
    {
        *p=20;//操作空间
    }
    int* ptr=(int*)realloc(p,40);//扩大内存空间
        if(ptr!=NULL)
        {
            p=ptr;//把扩大后的地址ptr交给p来管理
        }
    return 0;
}

上面这个代码,p开辟了一个20字节的内存,我们想将内存空间扩大为40字节

第一种情况:如图,realloc调节内存时,如果初始内存(20字节)加上后面的未被分配内存大于或等于目标内存(40字节)时,要扩展的内存就加在原始内存后面,返回的起始地址依然是malloc开辟空间返回的起始地址。

第二种情况:如图,realloc在调节内存时,后面的内存不够时,此时realloc就会在堆上重新找一个适合大小的连续空间来使用,因此就会返回一个新的起始地址。会经历以下过程:
(1)在堆区上找到新的内存空间,并且新的内存空间是连续且满足调节后的内存大小的。

(2)将原来空间的数据拷贝一份到新的空间来。

(3)释放旧空间

(4)返回新的内存的起始地址。

realloc可以进行完成和malloc一样的功能:

realloc(NULL,20)=malloc(20);

  • 35
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值