58 动态内存分配
1,C程序中,不同数据在内存中分配说明
①全局变量---内存中的静态存储区
②非静态的局部变量---内存中的动态存储区----stack 栈
③临时使用的数据 --- 建立动态内存分配区域,需要时随时开辟,不需要时及时释放 --- heap 堆
④根据需要向系统申请所需大小的空间,由于未在声明部分定义其为变量或者数组,不能通过变量名或者数组名来接收这些数据,只能通过指针来调用
2,动态内存分配的相关函数
①头文件 #include<stdlib.h> 声明了四个关于动态分配的函数
②函数原型 void* malloc(usigned int size) //memorey allocation
作用:
在内存的动态存储区(堆区)中分配一个长度为size的连续空间
形参size 的类型为无符号整型,函数返回值是所分配区域的第一个字节的地址,即此函数是一个指针型函数,返回的指针指向该分配域的开头位置
malloc(100):开辟100字节的临时空间,返回值为其第一个字节的地址
③函数原型 void *calloc(unsigned n, unsigned size)
作用------在内存的动态存储区中分配 n 个长度为 size 的连续空间,这个空间一般比较大,足以保存一个数组
用calloc函数可以为一维数组开辟动态存储空间,n 为数组元素个数,每个元素长度为 size
函数返回指向所分配域的起始位置的指针,分配不成功,返回NULL
p=calloc(50,4):开辟50*4 个字节的临时空间,把起始地址分配给指针变量 p
④函数原型 void free(void *p)
作用----释放变量 p 所指向的内存空间,使这部分空间能重新被其他变量使用
p 是最近一次调用 calloc 或 malloc 函数时的函数返回值
free 函数无返回值
free(p) : 释放 p 所指向的已分配的动态空间
⑤函数原型 void *realloc(void *p , unsigned int size)
作用----重新分配malloc或 calloc 函数获得的动态空间大小,将 p 指向的动态空间大小改变为size,p的值不变,分配失败返回NULL
realloc(p,50):将 p 所指向的已分配的动态空间 改为 50字节
⑥返回类型说明:
3,动态创建数组,输入5个学生的成绩,另外一个函数检测成绩低于60分的,输出不合格的成绩。
1 #include<stdlib.h> 2 void check(int* p) { //check中的p也指向堆区开辟的空间 3 printf("不及格的成绩有:\n"); 4 for (int i = 0;i < 5;i++) { 5 if (p[i] < 60) { //p[i]直接取到所指向的值 6 printf("%d\n", p[i]); 7 } 8 } 9 } 10 void main() { 11 int* p = (int*)malloc(20);//在堆区开辟一个5*4的空间,并将地址(void*)转成(int*),赋给p,也可以直接写作int* p=malloc(5*sizeof(int)),系统会自动转换 12 printf("请输入5个学生成绩:\n"); 13 for (int i = 0;i < 5;i++) { 14 scanf("%d", p+i);//p就是指针,这里不需要& 15 } 16 check(p); //将p指针传给check栈 17 free(p); //销毁堆区 即p指向的空间 18 }
4,动态内存分配的基本原则
①避免分配大量的小的内存块,分配堆上的内存有一些系统开销,所以分配许多小的内存块比分配几个大的内存块的系统开销大。
②仅在需要时分配内存,只要使用完堆上的内存块,就需要及时释放它(如果使用动态内存分配,需要遵守原则:谁分配,谁释放),否则可能出现内存泄漏
③总是确保释放以分配的内存,在编写分配内存的代码时,就要确定在代码的什么地方释放内存
④在释放内存之前,确保不会无意中覆盖堆上已分配的内存地址,否则程序就会出现内存泄漏,在循环中分配内存时,要特别小心