C语言中常见的动态内存申请函数(malloc、calloc、realloc)

目录

一、malloc(包含在头文件stdlib.h中)

        1.malloc的定义

        2.malloc的使用

二、calloc(包含在头文件stdlib.h中)

        1.calloc的定义

        2.calloc的使用

三、realloc(包含在头文件stdlib.h中)

        1.realloc的定义

        2.realloc的使用

        3.realloc申请扩容时空间内存解析


        在C语言中我们是否能按我们所需要的在系统中开辟想要大小的空间呢?当然没问题!本次博客来详细说一说一些常见的申请动态内存的函数(malloc、calloc、ralloc):

一、malloc(包含在头文件stdlib.h中)

        1.malloc的定义

                 >该函数有一个参数size,通过此参数向堆区申请size大小字节的连续空间(该函数不对申请的空间的数值做初始化)

                >返回一个指向该空间起始处的void*类型的指针,当空间申请失败时会返回一个空指针。

                >如果size为0,malloc的行为是不确定的,取决于编译器。

        2.malloc的使用

                当我们想好要申请要开辟的字节,通过malloc函数开辟成功时我们一般不用void*类型的指针来接收malloc的返回值。因为void*类型的指针不好解引用,也不方便管理开辟的空间。

        例如:

	int* p = (int*)malloc(40);

                我们向内存的堆区空间申请了40个字节的空间(相当于在空间中开辟了10个int类型的变量),再强转型成int*类型的指针交给p来管理,这样我们可以一次访问4个字节的空间。当然我们在申请空间时也要根据具体情况来申请,想清楚用什么类型的指针管理最合适。

                当然我们申请空间时也会出现申请失败的情况

        例如:当我们申请开辟的空间过大时:

                 此时malloc会返回一个空指针,所以我们在申请完时要判断是否开辟空间成功,不能盲目进行下一步(可以通过strerror函数来报错):

                 在我们使用完申请的空间时,该空间因为在堆区不能自动释放(除非程序运行结束)所以在我们不使用该空间时要及时释放以免影响程序运行:

int main()
{
	//申请
	int* p = (int*)malloc(40);
	//判断
	if (p == NULL)
	{
		printf("%s\n", strerror(errno));
		return 1;
	}
	//使用
	int i = 0;
	for (i; i < 10; i++)
	{
		*(p + i) = i;
	}
	//释放
	free(p);
	p = NULL;
	return 0;
}

                释放空间时我们使用函数free,此时交给函数free的指针应指向申请空间的起始地址,如果p被改动我们要找到申请空间的起始地址交给free函数否则就不能释放全部申请的空间造成浪费。完全释放完申请的空间时,p应置为空,以免形成野指针影响程序运行。

二、calloc(包含在头文件stdlib.h中)

        1.calloc的定义

                 >该函数有两个size_t类型的参数num和size,意思是向堆区申请num个size字节大小的连续的空间,并返回一个指向起始开辟空间的void*类型的指针。

                >该函数会对申请的空间的数值做初始化,将每个字节的空间的数值赋值为0

                >当空间申请失败时会返回一个空指针。

        2.calloc的使用

                和malloc函数一样,我们一般也不用void*类型的指针来接收其返回值。

        如:

                 第一个图是指针p的监视,第二个图是p指针的内存情况。从中我们可以很清楚的看到calloc函数对所开辟的空间都做了值为0的初始化(这意味着calloc比malloc函数更人性化,但是同时效率也相对更低)。

                由于calloc函数和malloc函数基本相同的性质我们也要对所开辟的空间及时的做出检查和释放以免影响程序的正常进行:

int main()
{
	//申请
	int* p = (int*)calloc(10,sizeof(int));
	//判断
	if (p == NULL)
	{
		printf("%s\n", strerror(errno));
		return 1;
	}
	//使用
	int i = 0;
	int* pp = p;
	for (i; i < 10; i++)
	{
		*p = i;
		p++;
	}
	//释放
	free(pp);
	pp = NULL;
	return 0;
}

                 在这里由于p指针在使用时被改变了,我们使用指针pp来指向开辟空间的起始地点,再将pp交给free函数来完全释放开辟的空间。

三、realloc(包含在头文件stdlib.h中)

        1.realloc的定义

         >realloc函数可以更改指向的动态空间的大小。

        >通过void*类型的指针prt传给realloc函数将要改变空间的起始地址,通过size_t类型的参数size传给realloc函数此空间将要改变后的大小。

        >申请成功后会返回一个void*类型的指向更改完成后起始空间位置的指针。

        >当空间申请失败时会返回一个空指针。

        >该函数扩容时结束后和传入空间地址不一定一致。

        >当ptr传入空指针时,该函数直接申请开辟一个新的size字节大小的空间。

        2.realloc的使用

int main()
{
	//申请
	int* p = (int*)malloc(40);
	//判断
	if (p == NULL)
	{
		printf("%s\n", strerror(errno));
		return 1;
	}
	//使用
	int i = 0;
	for (i; i < 10; i++)
	{
		*(p + i) = i;
	}
	//增加空间
	int* ptr = (int*)realloc(p, 80);
	if (ptr != NULL)
	{
		p = ptr;
	}
	//释放
	free(p);
	p = NULL;
	return 0;
}

        观察以上例子:该段 代码没有直接拿p指针来直接接收realloc的返回指针,原因在于如果空间申请失败将会返回一个空指针,如果将空指针赋给p我们不仅不会拿到新的空间还会丢失原来的开辟的40个字节的空间。为了保险我们临时创建指针ptr来接收realloc的返回值,当它申请成功时再将其空间交给p。

        3.realloc申请扩容时空间内存解析

                在使用realloc函数时,该函数在扩容时的过程应该是什么样的呢?

                 我们模拟一下堆区内存的使用情况,在p处有足够的空间时realloc会从p指向的最后空间直接向后扩容,当要扩容时p向后扩展的空间不足了应该怎么办呢?realloc会找到一个足够大的空间在此处创建一个扩容后大小的空间,再将p所指向原来空间的数据一一对应拷贝到新的空间当中:

                 最后再释放p所指向的原来的空间,再将新空间的初始地址返回。


本次的博客又要结束啦,欢迎大家在评论区指出不足,886~

C语言,`malloc` 和 `realloc` 函数是用于动态内存分配的两个关键函数,它们分别用于申请内存和重新分配内存。 1. `malloc`(memory allocation)函数用于动态分配一块指定大小的内存区域。当调用`malloc`时,它会在堆上查找一块足够大的空闲内存区域,如果找到,就返回这块内存区域的指针(一个指向该内存起始地址的指针),否则返回`NULL`。`malloc`并不会将这块内存初始化,内存的值是不确定的。 2. `realloc`(reallocation)函数用于重新分配之前用`malloc`、`calloc`或`realloc`分配的内存块。如果你需要更大的内存空间,`realloc`可以扩展已有的内存块,或者在需要的情况下移动内存块到新的位置。如果新的内存大小大于原先的大小,`realloc`可能会将内存块移动到新的位置,并返回新的内存块的指针;如果新的内存大小小于原先的大小,`realloc`可能会调整内存块的大小,保留原有数据。 观察内存地址变化的情况,通常需要在使用`malloc`和`realloc`前后打印指针变量的值。但是需要注意的是,因为内存分配和释放是动态的,所以每次程序运行时,即使是同样的分配过程,所得到的内存地址都可能不同。此外,由于操作系统的内存管理机制,连续的两次`malloc`可能会得到不连续的内存地址。 下面是一个简单的C语言代码示例,演示如何使用`malloc`和`realloc`,并打印内存地址的变化: ```c #include <stdio.h> #include <stdlib.h> int main() { int *ptr = malloc(sizeof(int)); // 分配内存,并打印地址 if (ptr == NULL) { return -1; } printf("malloc allocated address: %p\n", (void*)ptr); // 使用realloc来改变之前分配的内存大小 int *temp = realloc(ptr, 2 * sizeof(int)); if (temp == NULL) { free(ptr); // 如果realloc失败,释放原来的内存 return -1; } ptr = temp; // 更新指针 printf("realloc allocated address: %p\n", (void*)ptr); free(ptr); // 释放内存 return 0; } ```
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

1e-12

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

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

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

打赏作者

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

抵扣说明:

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

余额充值