一、 动态内存分配
1.传统数组的缺点:
①.数组长度必须事先确定,且只能是常整数,不能是变量
例子: int len =5, int a[len] //错误
②.传统形式定义的数组,该数组的内存程序员无法手动释放
在一个函数运行期间,系统为该函数中的数组所分配的空间,会一直存在,直到该函数运 行完毕时,数组空间才会被系统释放
③ 数组的长度一旦定义,其长度就不能再更改
④ A函数定义的数组,在A函数运行期间被其他函数使用,但A函数运行完毕后,A函数中的 数 组就不能被其他函数使用
2.为什么需要动态分配内存
动态分配内存很好的解决了传统数组的4个缺陷
3.动态内存分配的举例
# define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<malloc.h>
/*
2024年5月11日17:02:57
malloc是memory(内存)allocate(分配)的缩写
*/
int main()
{
int i = 5; //静态分配,4个字节
int* p = (int*)malloc(4); //最终分配了8个字节,p变量占4个字节,P所指向内存也占4个字节
/*
1.使用malloc函数,必须包含#include<malloc.h>头文件
2.malloc函数只有一个形式参数,并且是整型
3.malloc(4)中的4表示请求系统为本程序分配4个字节
4.malloc函数只能返回第一个字节的地址
5.p本身所占的内存是静态分配的,P所指向的内存是动态分配的
*/
free(p); //表示把P所指向的内存给释放掉,p本身的内存是静态的没有释放,只能函数结束后,系统来释放
printf("好难啊\n");
return 0;
}
# define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<malloc.h>
void f(int* q)
{
*q = 2000;
}
int main(void)
{
int* p = (int*)malloc(sizeof(int));
*p = 10;
printf("%d\n", *p); //结果 10
f(p);
printf("%d\n", *p);//结果 2000
return 0;
}
动态一维数组的构造
# define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<malloc.h>
//动态一维数组
int main(void)
{
int a[5];//如果int占4个字节,本数组总共占20个字节,定义了一个静态数组a
int len;
int* pArr;
int i;
//动态一维数组的构造
printf("请输入你要存放的元素个数:");
scanf("%d", &len);
pArr = (int*)malloc(4 * len);
//动态的构造了一个一维数组,该数组的数组名是pArr,长度是len,数据类型是int
//其功能类似于 int pArr[len]
//对动态一维数组进行赋值
for (i = 0; i < len; i++)
{
scanf("%d", &pArr[i]);
}
//对一维数组进行输出
for(i = 0; i < len; i++)
{
printf("%d\n", pArr[i]);
}
free(pArr);//释放掉动态分配的数组
return 0;
}
4.静态内存和动态内存的比较
- 静态内存
静态内存是由系统自动分配和释放
静态内存是在栈分配的
- 动态内存
动态内存是由程序员手动分配,手动释放
动态内存是在堆分配的
5.跨函数使用内存的问题
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<malloc.h>
//跨函数使用内存
void f(int** q) //q是指针变量,无论q什么类型指针变量,都占4个字节
{
*q = (int*)malloc(sizeof(int));//*q等价p
**q = 5; //等价 *p=5
}
int main(void)
{
int* p;
f(&p);
printf("%d\n", *p);
return 0;
}