前言
对于使用数组或者是使用变量开辟内存,往往存在以下劣势之处
1. 空间开辟大小是固定的。
2. 数组在申明的时候,必须指定数组的长度,它所需要的内存在编译时分配。
但是对于空间的需求,不仅仅是上述的情况。有时候我们需要的空间大小在程序运行的时候才能知道,那数组的编译时开辟空间的方式就不能满足了。
那对于此类问题怎么解决呢,小编就给大家带来今天的主角。
1.动态内存函数的介绍
1.1 malloc函数
malloc的功能是开辟一个连续的动态内存,具体使用和细节如下
void* malloc (size_t size);
1.这个函数向内存申请一块连续可用的空间,并返回指向这块空间的指针。
2.如果开辟成功,则返回一个指向开辟好空间的指针。
3.如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查。(需要用if语句判断,再使用strerror函数返回错误信息)
4.返回值的类型是 void* ,所以malloc函数并不知道开辟空间的类型,具体在使用的时候使用者自己来决定。
5.如果参数 size 为0,malloc的行为是标准是未定义的,取决于编译器。(size表示的是多少个字节的内存大小)
使用展示
#include <stdio.h> #include<stdlib.h>//头文件,使用时记得添加 #include<string.h>//strerror函数使用的头文件 #include<errno.h>//为了使用errno变量 int main() { char* p = (char*)malloc(sizeof(char) * 26);//这里表示开辟一个内存大小为26字节的内存,用指针p指向 if (p == NULL)//判断malloc函数是否申请成功,如果申请失败,直接结束函数 { printf("%s ",strerror(errno)); return 1; } int i = 0; for (i = 0; i < 26; i++) { p[i] = 'A' + i; } for (i = 0; i < 26; i++) { printf("%c",p[i]); } free(p); p = NULL; return 0; }
结果展示:
这里大家可以看到一个新的函数free,这是专门是用来做动态内存的释放和回收的。对于这个函数介绍如下
1.2 free函数
void free (void* ptr);
free函数用来释放动态开辟的内存。,如果参数 ptr 指向的空间不是动态开辟的,那free函数的行为是未定义的。如果参数 ptr 是NULL指针,则函数什么事都不做。(注意:free只能释放动态开辟的空间)
1.2.1 free函数的重要性
对于自动变量,该在内存使用的数量在程序执行期间会自动地增加,减少,但对于动态分配的内存,只会增加,,除非使用free函数进行释放。如果内存不及时释放,会导致内存泄漏,甚至可能导致系统地崩盘。
1.3 calloc函数
calloc函数的使用效果大概一致,但也有一些不同,至于有哪些不同呢?接下来听小编细细道来
void* calloc (size_t num, size_t size);
calloc函数的功能是为 num 个大小为 size 的元素开辟一块空间,并且把空间的每个字节初始化为0,与函数 malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全0。
对于返回值: 成功时,指向函数分配的内存块的指针。如果函数无法分配请求的内存块,则返回空指针。(需要用if语句判断,在使用strerror函数返回错误信息),使用后也需要用free释放。
使用展示:
#include <stdio.h> #include<stdlib.h>//头文件,使用时记得添加 #include<string.h>//strerror函数使用的头文件 #include<errno.h>//为了使用errno变量 int main() { char* p = (char*)calloc(26,sizeof(char));//这里表示开辟一个内存大小为26字节的内存,用指针p指向 if (p == NULL)//判断malloc函数是否申请成功,如果申请失败,直接结束函数 { printf("%s ", strerror(errno)); return 1; } int i = 0; for (i = 0; i < 26; i++) { p[i] = 'A' + i; } for (i = 0; i < 26; i++) { printf("%c",p[i]); } free(p); p = NULL; return 0; }
这里我们打开调试看一下calloc申请后内存中的存储内容:
这里可以看到由calloc申请动态内存空间后,内部被自动初始化为0
运行结果:
1.4 realloc函数
对于动态内存函数中是否有一个函数具有对动态开辟内存大小的调整的功能呢?这里realloc函数具有的正是这个作用。
void* realloc (void* ptr, size_t size);
这里ptr 是要调整的内存地址,size 指的是调整之后新大小(可以调大也可以调小)(当ptr为空指针时realloc和malloc函数的作用时一致的)
返回值为调整之后的内存起始位置。失败后直接返回空指针。那对于返回的的地址,它是之前动态产生的旧地值呢,还是会返回一个新的地址呢?这里我们需要分情况讨论。
情况1:原有空间之后有足够大的空间
情况2:原有空间之后没有足够大的空间
情况1
当是情况1 的时候,要扩展内存就直接原有内存之后直接追加空间,原来空间的数据不发生变化。
情况2
当是情况2 的时候,原有空间之后没有足够多的空间时,扩展的方法是:在堆空间上另找一个合适大小的连续空间,然后把旧的空间的数据拷贝到新空间前面的位置,并且把旧的空间释放掉,同时返回新空间的地址
使用展示:
#include <stdio.h> #include<stdlib.h>//头文件,使用时记得添加 #include<string.h>//strerror函数使用的头文件 #include<errno.h>//为了使用errno变量 int main() { char* p = (char*)malloc(24 * (sizeof(char)));//这里表示开辟一个内存大小为24字节的内存,用指针p指向 if (p == NULL)//判断malloc函数是否申请成功,如果申请失败,直接结束函数 { printf("%s ", strerror(errno)); return 1; } char* ptr = (char*)realloc(p, 400*sizeof(char));/*这里最好不要使用原指针指向,如果申请失败会导致,原指针指向 空指针,导致内存泄漏 */ if (ptr != NULL) { p = ptr; ptr = NULL; } int i = 0; for (i = 0; i <26; i++) { p[i]= 'A' + i; } for (i = 0; i < 26; i++) { printf("%c", p[i]); } free(p); p = NULL; return 0; }
结果显示: