0
点赞
收藏
分享

微信扫一扫

C语言问题集——动态内存分配(1)

佳简诚锄 2022-04-07 阅读 100

1、引入:

一般开辟内存空间的方法:

int g_val = 0; //在栈空间上开辟4个byte。

int array [10] = {0}; //在栈空间上开辟40个byte的连续空间。

或者int array [] = {0,1};//在栈空间上开辟8个字节的连续空间。

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

1、空间开辟大小是固定的。

2、数组在申明的时候,必须指定数组的长度,或是初始化所需要的元素,它所需要的内存在编译期间分配。

这就意味着我们需要在创建的时候就知道我们需要多少的空间,但是有时候我们所需的空间大小往往是在编写的过程中才知道,或者说需要调整,但是上述的方法显然是不能满足我们的需求的,此时就需要动态内存分配:

首先要了解内存的布局:

内存大致被分为这么几个区域,其中内核空间是用来留给操作系统以及关键组件的,是用户代码不能读写的,栈区主要用来存放局部变量以及函数形参,堆区主要用来动态内存分配,所谓的数据段也就是静态区,主要用来存放static修饰的静态变量和创建的全局变量。

        所以,动态内存是在堆区开辟的。

2、动态内存开辟函数介绍:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
int main()
{
	int i = 0;
	int* p = (int*)calloc(5, sizeof(int));//开辟动态内存空间
	if (p != NULL)
	{
		//使用
		for (i = 0; i < 5; i++)
		{
			*(p + i) = i;
		}
		for (i = 0; i < 5; i++)
		{
			printf("%d ", *(p + i));
		}
	}
	else
	{
		printf("%s\n", strerror(errno));
	}
	//释放
	free(p);
	p = NULL;


	return 0;
}

malloc 和 calloc 的区别:

malloc函数在开辟空间时,只是给了一块空间的访问权限,但并未对所申请区域的数据进行初始化,而calloc函数在开辟时,会将所申请区域的数据全部初始化为0。(未初始化时内存空间内存储的是随机值)

如果我们在申请动态内存空间时,需要对所申请的空间初始化,那么可以使用calloc函数。

<3> realloc

realloc函数的出现让动态内存管理更加灵活。

realloc函数可以对动态开辟的内存大小进行调整。

memblock参数是需要调整的动态内存空间的指针,size参数是所需调整到的字节数。

返回值是调整之后的空间的首地址。

注:realloc函数在调整空间时,会有两种情况:

        1、原有空间之后有足够大的空间

那么就会在原有空间后面直接追加空间,原来空间的数据不发生改变。返回的指针指向的空间仍然是realloc之前的空间,不过是扩容了。

        2、原有空间之后没有足够大的空间

扩展的方法是:在堆空间上另外找一块合适大小的连续空间来使用,原有的数据会被挪到新开辟的空间中,返回的指针指向的空间也是新的。原来的那块空间就会被回收。

如果扩容失败,会返回NULL 。

所以在接收realloc返回的指针时,要创建一个中间变量,用来判断是否开辟成功,再决定是否将新开辟的空间交给原来的指针保管。若是直接将返回值交给缘来的指针,若开辟失败,原指针就被置为NULL,原数据也就不能访问了

使用例子:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
int main()
{
	int i = 0;
	int* p = (int*)calloc(5, sizeof(int));//开辟动态内存空间
	if (p != NULL)
	{
		//使用
		for (i = 0; i < 5; i++)
		{
			*(p + i) = i;
		}
		for (i = 0; i < 5; i++)
		{
			printf("%d ", *(p + i));
		}
	}
	else
	{
		printf("%s\n", strerror(errno));
	}
	printf("\n");
	//调整
	int* ptr = (int*)realloc(p, sizeof(int) * 10);
	if (ptr != NULL)
	{
		//使用
		p = ptr;
		for (i = 0; i < 10; i++)
		{
			*(p + i) = i;
		}
		for (i = 0; i < 10; i++)
		{
			printf("%d ", *(p + i));
		}
	}
	else
	{
		printf("扩容失败\n");
	}
	//释放
	free(p);
	p = NULL;


	return 0;
}

其中ptr就是一个中间变量。

特殊情况:

若给relloc传入空指针,即realloc(NULL, size);此时功能类似malloc 。

水平有限,欢迎指正。(下一篇就写写使用这些函数容易出错的点吧)

举报

相关推荐

0 条评论