动态内存分配与静态内存分配

文章目录

  • 一.静态内存管理
  • 二.动态内存管理
    • 1.为什么存在动态内存管理
    • 2.动态内存函数的介绍
      • 1).malloc
      • 2.calloc
      • 3.realloc
      • 4.free
      • 5.动态开辟空间代码的标准写法

一.静态内存管理

静态内存是指程序开始运行时,由编译器自动分配和释放空间。程序中的各种变量,在程序编译时都需要分配空间,当函数调用完,空间自动释放。此时**用户不需要关心空间的申请与释放问题。**通常都储存在栈中。
例如:

int i=20//在栈上开辟4字节的空间
char a[10]={0};//在栈上开辟10字节的空间

二.动态内存管理

1.为什么存在动态内存管理

静态内存管理由两个特点:

1.空间开辟的大小时固定的
2.数组在声明的时候,必须指定数组的长度,它所需要的内存在编译时分配。

而动态内存分配,可以很好的解决上面的问题,当需要开辟的空间不确定时,静态内存管理就不好定义变量的大小,这是使用动态内存,可以得到一个变常数组,大小可以由自己开辟。并且动态内存可以提供大块的内存。
注意:动态内存是在堆上开辟的,必须由程序员申请释放

2.动态内存函数的介绍

1).malloc

  • 表现形式
    在这里插入图片描述
    参数为需要开辟空间的大小,返回值为开辟空间的起始地址。
  • 特点
    1.如果开辟成功,则返回一个指向开辟好的空间的首地址。
    2.如果开辟不成功,则返回一个空指针(NULL),因此malloc的返回值一定要做判断是否为空。
    3.返回值为void*类型,所以具体使用时类型要有使用者决定,意思就是要强转类型。
    4.如果参数size为0,malloc的行为是标准还是未定义的,取决于编译器。
    注意:后面需要手动释放空间
  • 使用
	int a = 0;
	scanf("%d", &a);
	char *p = (char *)malloc(sizeof(char)*a);//在堆上开辟a字节的空间,
	//用指针p指向在堆上开辟空间的首地址。p在栈上开辟空间

2.calloc

  • 表现形式
    在这里插入图片描述
    返回值为void* 开辟空间的首地址,参数为num 个空间,size为空间的大小。
  • 作用
    作用与malloc作用相同,区别在于开辟num个大小为size的空间,并将空间的每一个字节初始化为0。
    注意使用后判定指针是否为空。并且后面需要手动释放空间
  • 使用
int *p=(int *)calloc(10,sizeof(int));//在堆上开辟40字节的空间,并且初始化为0。

3.realloc

  • 表现形式
    在这里插入图片描述
    返回值为void* 开辟空间的首地址,参数ptr为要调整的动态内存的首地址。size为调整之后的新大小。
  • 作用
    有时我们发现之前申请的空间太小了或者太大了,realloc函数可以做到对动态开辟内存大小的调整,其它作用与malloc作用相同。
    注意:使用后判断地址是否为空。并且后面需要手动释放空间
    realloc函数调整地址有三种情况:
    1.开辟空间过大,返回地址与需要调整空间的地址相同,只要将空间缩小。
    动态内存分配与静态内存分配_第1张图片
    2.开辟空间过小,原有空间之后有足够大的空间,返回地址与需要调整空间的首地址相同,只要将空间向后扩大。
    动态内存分配与静态内存分配_第2张图片
    3.开辟空间过小,原有空间之后没有足够大的空间,需要在另外足够大的空间处重新开辟空间,返回地址与要调整地址不同。
    动态内存分配与静态内存分配_第3张图片
  • 使用:
int *prt=(int *)malloc(sizeof(int)*10);
int *p=(int *)realloc(prt.100);

注意:

prt=realloc(prt,100);//错误

如果prt空间小了,要调整大一点,如果realloc函数调整后,返回地址与原来不相同,prt指向新地址,但是prt原来的小地址空间还在,如果prt指向新地址,原来开辟的小的地址空间就找不到了。造成内存泄露。

4.free

  • 表现形式
    在这里插入图片描述
    不需要返回值,参数为动态申请空间的首地址。
  • 作用:
    用来释放动态开辟的内存
    1.如果prt指针指向的空间不是动态开辟的,那么free行为是未定义的。
    2.如果参数prt是NULL指针,则free函数什么都不做。

5.动态开辟空间代码的标准写法

#include
#include
int main()
{
	int a = 0;
	scanf("%d", &a);
	int *p = (int *)malloc(sizeof(int)*a);
	if (p == NULL){//判断空间是否开辟成功
		printf("malloc error\n");
		return 1;
	}
	for (int i = 0; i < a; i++){
		*(p + i) = 0;
	}
	free(p);//是否开辟空间
	p = NULL;//防止成为野指针
	return 0;
}

注意点:
1. 动态开辟的空间必须free释放,不然会导致内存泄露
2.free函数只是切断了指针与堆(开辟的内存)之间的联系,指针里存的内容没变,只是不能指向堆了。为了防止指针变成野指针,最后要让指针指向NULL。
3.删除数据不是将数据全部清空,只是设成了无效。

你可能感兴趣的:(C语言,内存管理,c#)