动态内存分配与静态内存分配
Posted 两片空白
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动态内存分配与静态内存分配相关的知识,希望对你有一定的参考价值。
一.静态内存管理
静态内存是指程序开始运行时,由编译器自动分配和释放空间。程序中的各种变量,在程序编译时都需要分配空间,当函数调用完,空间自动释放。此时**用户不需要关心空间的申请与释放问题。**通常都储存在栈中。
例如:
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.开辟空间过大,返回地址与需要调整空间的地址相同,只要将空间缩小。
2.开辟空间过小,原有空间之后有足够大的空间,返回地址与需要调整空间的首地址相同,只要将空间向后扩大。
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<stdio.h>
#include<stdlib.h>
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.删除数据不是将数据全部清空,只是设成了无效。
以上是关于动态内存分配与静态内存分配的主要内容,如果未能解决你的问题,请参考以下文章