动态内存分配
知识点结构:
- 传统数组的缺点
- 为什么需要动态内存分配
- 动态内存分配举例——动态数组的构造
- 静态内存和动态内存的比较
- 跨函数使用内存的问题
一、传统数组的缺点
- 数组长度必须事先指定,且只能是常整数,不能是变量
例:
int a[5];//ok
int len = 5; int a[len];//error,现在可以 - 传统形式定义的数组,该数组的内存程序员无法手动释放,直到所在函数运行结束
- 数组的长度无法在函数运行的过程中动态的扩充或缩小
- A函数定义的数组,在A函数运行期间可以被其他函数使用,但A函数运行完毕之后,A中的数组将无法再被其他函数使用
传统方式定义的数组不能跨函数使用
二、为什么需要动态内存分配
- 动态数组很好的解决了传统数组的4个缺陷
- 传统数组也叫动态数组
malloc函数的使用:
int main()
{
int i = 5; //①分配了4个字节,静态分配①
int * p = (int *)malloc(4);
/*
1.使用malloc()要添加malloc.h头文件
2.malloc函数只有一个形参,并且都是整形
3.形参表示系统为本程序分配的字节数
4.malloc函数只能返回第一个字节的地址
5.p本身所占的内存是静态分配的,p所指向的内存是动态分布的
*/
*p = 5;//*p代表的就是一个int变量,只不过*p这个类型变量的内存分配方式和①不同
free(p);//free(p)表示把p所指向的内存给释放掉
printf("Hello!\n");
return 0;
}
void f(itn *q)
{
//*p = 200;error
// q = 200;error
// **q = 200;error
*q = 200;
free(q);//指针q指向的空间被释放
}
int main(void)
{
int * p = (int *)malloc(sizeof(int));
*p = 10;
print("%d\n",*p);
f(p);
printf("%d\n",*p);
return 0;
}
三、动态内存分配举例——动态数组的构造
动态一维数组的构造:
- 在使用上和静态数组无异
int main(void)
{
int a[5];
int len;
int * pArr;
int i;
//动态的构造一维数组
printf("请输入你要存放的元素个数");
scanf("%d",&leb);
pArr = (int *)malloc(4 * len);//等于pArr[len]
/* 构造的动态一维数组在使用上和静态数组无异 */
//对一维数组进行操作
for(i=0;i<len,i++)
scan("%d",&pArr[i]);
//对一维数组进行输出
for(i=0;i<len;i++)
printf("%d",pArr[i]);
//释放动态分配的数组
free(pArr);
return 0;
}
四、静态内存和动态内存的比较
- 静态内存是在栈分配的,静态内存是由系统自动分配,由系统自动释放
- 动态内存是在堆分配的,动态内存是由程序员手动分配,手动释放
五、跨函数使用内存的问题
- 静态变量不能跨函数使用
void f(int ** q)
{
int i = 5;
*q = &i;
}
int main(void)
{
int *p;
f(&p);
print("%d\n",*p); //输出5,语法无问题,但逻辑上有问题,在f函数中,f运行结束i已经被释放,main无权使用,只有指针会出现此问题
return 0;
}
- 动态变量可以跨函数使用
void f(int **q)
{
*q = (int *)malloc(sizeof(int));
**q = 5; // *p = 5;
}
int main(void)
{
int * p;
f(&p);
printf("%d\n",*p);//动态分配,未手动释放,可以使用f函数创建的空间
return 0;
}
------------------------------------------------------------------------------------------------------------
本文作者:ZyNu11
------------------------------------------------------------------------------------------------------------