1.内存管理的基本概念
1.1内存分配方式 1)从静态存储区域分配。内存在程序编译的时候就已经分配好了,这块内存在程序的整个运行期间都存在。例如全局变量,static变量
2)在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,该函数执行结束时这些存储单元自动释放。 3)在堆上分配。也称为动态分配,程序在运行的时候分配的内存。
2常见的内存分配函数
2.1 为什么要进行动态内存分配? 以数组威力,一个数组的元素是存储于内存中连续的位置。当数组被声明时其所需要的内存在编译时就已经分配好了。但有些时候静态分配是不方便的。例如使用数组存储班级中所有学生的成绩,但是不同的班级中学生的个数是不同的。在这种情况下,应该给该数组分配多大的内存?一般是按照可以容纳可能出现的最多元素来做
这样做的优点:简单 缺点:声明中引入了限制,如果程序需要使用的元素超过了声明的长度,会出现问题。 1)解决上面的问题的方法就是把数组声明的更大一些。但是又会导致内存的浪费 2)如果超过数组容纳的范围时,程序必须有合理的响应。不应该由于一个异常而导致失败,但也不应该printf看上去正确但实际错误的结果
2.2常减动态内存分配函数 1)voidzmalloc(unsigned size)。其中size就是指分配内存的字节。其作用是在内存的堆区分配大小为size个字节的连续的内存空间,如果分配成功就返回该段内存空间的首地址,否则就返回NULL,所以在分配内存空间时要判断是否分配成功。 返回值是void*,可以强制转换成人和类型。 例如:- // =赋值要求两边的类型一致
- int *p = (int*)malloc(4*sizeof(int));
-
- if(p != NULL) {
- //如果申请成功
- memset(p,'B',16);
-
- for (int i = 0; i < 4; i++) {
- printf("%c ",*(p+i));
- }
- } else{
- //如果申请失败
- }
复制代码 注意:malloc申请的内存空间,如果不赋值,那么空间里的是垃圾数
2)calloc 分配函数 例如: - //calloc分配
- //格式calloc(块数,长度)
- int *p = calloc(4, sizeof(int));//分配了4块,每块长度位4自己的连续的内存空间.跟数组差不多
- if(p != NULL) {
- //如果申请成功
- memset(p,'B',16);
-
- for (int i = 0; i < 4; i++) {
- printf("%c ",*(p+i));
- }
- } else{
- //如果申请失败
- }
复制代码
注意:calloc会自动初始化空间位0
3)realloc 分配函数 - int *str = (int *)malloc(4*sizeof(int));//16字节
-
- printf("old address = %p\n", str);
- int a = 9;
- int *str2 = (int *)malloc(4*sizeof(int));
- printf("old2 address = %p\n", str2);
- //如果发现当前分配的16个字节不够用了,那么需要扩展str的内存空间
- //realloc可以给已经存在内存空间扩展大小.但是分配的空间并不一定连续。如果原空间后面有充足的剩余空间,那么可以与原空间地址连续,否则会在内存的其他位置寻找剩余的连续空间分配,然后返回新空间的首地址。
- int *p = realloc(str2, 26);
- printf("new address = %p", p);
复制代码
打印结果: old address = 0x100103a90 old2 address = 0x100103aa0 new address = 0x100103ab0
|