c语言动态内存分配
来源:互联网 发布:北京达内java 编辑:程序博客网 时间:2024/05/17 07:33
数组的元素存储于内存连续位置上。当一个数组被声明时,它所需要的内存在编译时期就会被分配。但是,你也可以使用动态内存分配在运行时为他分配内存。我们如何使用动态内存分配以及怎样进行动态内存分配?
c语言中的内存区域
C语言中内存分为四区:
- 栈区:由编译器自动分配释放,存放函数的参数,局部变量的值。
- 堆区:由程序员分配释放,即动态内存的申请和释放。
- 全局区:全局变量和静态变量是放在一块的。初始化的全局变量和未静态变量在同一个区域,未初始化的全局变量和静态变量在相邻的另外一个区域
- 代码区:存放函数体的二进制代码。
- 文字常量区:常量字符串就是放在这里,程序结束后由系统释放。
这里需要注意的是堆和栈的最主要的区别,栈区是编译期自动释放,无需手动释放,而堆区需要程序员手动释放。
内存分配在堆栈中的区别
内存分配分为两种:
- 静态分配。
静态内存分配,分配内存大小的是固定,问题:1.很容易超出栈内存的最大值 2.为了防止内存不够用会开辟更多的内存,容易浪费内存。
int a[1024 * 1024 * 10];
比如上面的代码就是静态内存分配。
动态分配。
当一个数组被声明时,它所需要的内存在编译时期就被分配。你也可以使用动态内存分配在运行时为它分配内存。
动态内存分配,在程序运行过程中,动态指定需要使用的内存大小,手动释放,释放之后这些内存还可以被重新使用。
malloc 和 free
c函数库中提供了两个函数,malloc和free。分别用来执行动态内存的分配和释放。
这两个函数都在stdlib.h中声明。
void *malloc( size_t size);void *free(void * pointer);
使用时需要导入
#include <stdlib.h>
malloc
- malloc 参数就是分配的内存字节数,返回的是内存块起始的指针。
- malloc分配一块连续的内存,并不会分开两块或者多块内存的区域。
- 如果内存池是空的,内存无法满足你的请求,就会返回一个NULL指针
free
free参数要么为NULL,要么是malloc,calloc,或者realloc返回的值。
向free传递一个NULL,不会产生效果。
代码示例:
1.创建一个静态数组。
#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>#include <stdlib.h>#include <Windows.h>//栈内存void stackFun(){ int a[1024]; //栈内存自动释放}//堆内存void heapFun(){ //40M内存 //字节 //void *任意类型的指针 int* p = malloc(1024 * 1024 * 10 * sizeof(int)); //释放 free(p);}void main(){ //在堆内存上,分配40M的内存 while (1){ Sleep(1000); stackFun(); } getchar();}
如代码中,我们定义一个while循环,分别对堆内存和栈内存进行分配。我们会发现堆内存会不断上涨。如果使用free,就不会出现这种情况。而栈内存不会增长。
free(p);
2.创建一个数组,动态指定数组的大小
#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>#include <stdlib.h>#include <Windows.h>//创建一个数组,动态指定数组的大小void main(){ //静态内存分配创建数组,数组的大小是固定的 //int i = 10; //int a[i]; int len; printf("输入数组的长度:"); scanf("%d",&len); //开辟内存,大小len*4字节 int* p = malloc(len * sizeof(int)); //p是数组的首地址,p就是数组的名称 //给数组元素赋值(使用这一块刚刚开辟出来的内存区域) int i = 0; for (; i < len - 1; i++){ p[i] = rand() % 100; printf("%d,%#x\n", p[i], &p[i]); } //手动释放内存 free(p); getchar();}
realloc和calloc
realloc 和 calloc的原型如下:
void *calloc( size_t num_elements,size_t element_size);void *realloc(void *ptr, size_t new_size);
calloc
用于分配内存。malloc和calloc之间的主要区别就是calloc在返回指向内存的指针之前把它初始化为0。
另一个较小的区别就是,calloc的参数包括所需元素的数量和每个元素的字节数。根据这些值,他就能计算出总共需要分配的内存。
realloc
用于修改一个原先已经分配内存的大小,可以使一块内存扩大或者缩小。
重新分配内存分为两种情况:
- 缩小
- 扩大(连续的)
- 如果当前内存段后面有需要的内存空间,直接扩展这段内存空间,realloc返回原指针。
- 如果当前内存段后面的空闲字节不够,那么就使用堆中的第一个能够满足这一要求的内存块,将目前的数据复制到新的位置,并将原来的数据库释放掉,返回新的内存地址。
- 如果申请失败,返回NULL,原来的指针仍然有效。
- realloc参数第一个为NULL,那么它的行为就和malloc一样。
代码演示
#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>#include <stdlib.h>#include <Windows.h>//realloc 重新分配内存void main(){ int len; printf("第一次输入数组的长度:"); scanf("%d", &len); //int* p = malloc(len * sizeof(int)); int* p = calloc(len, sizeof(int)); int i = 0; for (; i < len; i++){ p[i] = rand() % 100; printf("%d,%#x\n", p[i], &p[i]); } int addLen; printf("输入数组增加的长度:"); scanf("%d", &addLen); //内存不够用,扩大刚刚分配的内存空间 //1.原来内存的指针 2.内存扩大之后的总大小 int* p2 = realloc(p, sizeof(int) * (len + addLen)); if (p2 == NULL){ printf("重新分配失败,世界那么大,容不下我。。。"); } //重新赋值 i = 0; printf("--------------------------\n"); for (; i < len + addLen; i++){ p2[i] = rand() % 200; printf("%d,%#x\n", p2[i], &p2[i]); } //手动释放内存 /**if (p != NULL){ free(p); p = NULL; } if (p2 != NULL){ free(p2); p2 = NULL; } **/ getchar(); system("pause");}
结果为:
从图中可以看到数组首地址是不变的。
内存分配注意的几个细节
- 1.不能多次释放
- 2.释放完之后(指针仍然有值),给指针置NULL,标志释放完成
#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>#include <stdlib.h>#include <Windows.h>void main(){ int len; printf("输入数组的长度:"); scanf("%d", &len); int* p = malloc(len * sizeof(int)); int i = 0; for (; i < len; i++){ p[i] = rand() % 100; printf("%d,%#x\n", p[i], &p[i]); } if (p != NULL){ free(p); p = NULL; } getchar();}
- 3.内存泄露(p重新赋值之后,再free,并没有真正释放内存)
void main(){ //40M int* p1 = malloc(1024 * 1024 * 10 * sizeof(int)); //1处。 //free(p1); //p1 = NULL; printf("%#x\n",p1); //80M p1 = malloc(1024 * 1024 * 10 * sizeof(int) * 2); free(p1); p1 = NULL; getchar();}
如果1处注释掉。我们来看一下。windows任务管理器。第二个参数为内存占用。
如果把注释打开:
相差40m。
- C语言动态内存分配
- C语言动态内存分配
- C语言动态内存分配
- C语言 动态内存分配
- C语言动态内存分配
- c语言:动态内存分配
- C语言-动态内存分配
- c语言-动态内存分配
- C语言动态内存分配
- C语言动态内存分配
- c语言 动态内存分配
- C语言-动态内存分配
- C语言动态内存分配
- C语言 动态内存分配
- C语言 动态内存分配
- C语言 动态内存分配
- 【C语言】动态内存分配
- 【C语言】动态内存分配
- ruby on railst添加照片,翻译,美化界面及用户注册
- django的aggregate()和annotate()函数用法
- STM8学习笔记----按键中断
- ajax和json的post和get请求参数配置
- JQuery中的Ajax和插件
- c语言动态内存分配
- Servlet相关文件上传下载类总结
- 树状数组求解逆序问题
- 最大回文子串
- ADSFASDFASDF
- Service、IntentService、Thread的区别和联系
- 建立你的 GitHub (最傻瓜式教程,什么是GitHub?从安装到使用)
- DNS解析流程
- centOS6.8中mysql对用户的操作和授权