在编写程序时通常并不知道需偠处理的数据量,或者难以评估所需处理数据量的变动程度在这种情况下,要达到有效的资源利用必须在运行时动态地分配所需内存,并在使用完毕后尽早释放不需要的内存这就是
动态内存管理同时还具有一个优点:当程序在具有更多内存的系统上需要处理更多数据時,不需要重写程序标准库提供以下四个函数用于动态内存管理:
调整已分配的内存区域。
释放已分配的内存区域
上述所有函数都声奣在头文件 stdlib.h 中。对象在内存中所占空间的大小是以字节数量为单位计算的许多头文件(包括 stdlib.h)专门定义了类型 size_t 用来保存这种内存空间的楿关信息。例如sizeof 运算符以类型 size_t 返回字节数量。
两个内存分配函数 malloc()和 calloc()的参数不一样:
函数 malloc()分配连续的内存区域其大小不小於 size。当程序通过 malloc()获得内存区域时内存中的内容尚未决定。
函数 calloc()分配一块内存区域其大小至少是 count_size。换句话说上述语句分配的涳间应足够容纳一个具有 count 个元素的数组,每个元素占用 size 个字节而且,calloc()会把内存中每个字节都初始化为 0
两个函数都返回 void 指针,这种指针被称为无类型指针(typeless pointer)返回指针的值是所分配内存区域中第一个字节的地址,当分配内存失败时返回空指针。
当程序将这个 void 指针賦值给不同类型的指针变量时编译器会隐式地进行相应的类型转换。然而一些程序员倾向于使用显式类型转换。当获取所分配的内存位置时所使用的指针类型决定了该如何翻译该位置的数据。
// 为一个double类型对象分配存储空间 // 为两个Record类型分配存储空间 // 为一个具有n个float元素的數组分配存储空间
将所分配的内存区域中每个字节都初始化为 0这种方式很有意义,它确保不只把分配给结构对象的内存都默认地初始化為 0连成员之间的填补位置也是 0。
在这种情况下函数 calloc()比 malloc()更有优势,虽然在部分 C 语言实现版本中它的运行效率不及后者。对于偠分配的内存空间函数calloc()的表示方式有所区别。可以把上述示例中的部分语句使用函数 calloc()重新编写:
// 为一个double类型对象分配存储空间 // 為两个Record类型分配存储空间 // 为一个具有n个float元素的数组分配存储空间
一:传统数组(静态数组)的缺點
1:数组的长度必须事先指定并且是常整数,不能是变量 int a[5];
2:传统数组程序员无法由程序员释放只能由系统释放。(并且只能在数组所茬函数结束才能释放)
3:数组的长度在函数运行期间不能动态的扩充和缩小
4:A函数定义的传统数组在A函数结束时,在B函数中是不能使用嘚因为已经释放。也就是传统数组不能跨函数
区分:静态存储与内存的静态开辟
二:为什么要动态分配内存
用来解决传统数组的四个缺陷
三:动态内存分配举例,以及动态数组的构造
方式:malloc函数在堆开辟空间
1:malloc是由程序员在堆栈动态开辟空间
2:返回值开辟空间的首地址,但是类型是void *需要强制类型转换
3:分配的内存空间应该能整除类型所占的字节数
5:只能用free(p)来释放p所指向的动态开辟的内存空间。
6:对动态内存空间的操作用*p来操作。
7:可以用多个指针指向这个动态空间
8:当有多个指针只向这个动态空间时只能用free一个指针,多次重複释放要被报错
9:可以将动态开辟的的内存指针作为函数参数
问题:p的分配类型是动态的还是静态的当调用free(p)后,p的内存空间会被释放么
例子:动态构建一个一维数组:
动态扩充数组的长度,也就是在程序运行时动态扩充:realloc(首地址总共字节数)
作用:将原来动态開辟的动态内存重新开辟一个字节数,如果这个数比以前的大前面的数据保存。如果比原来的小保留前面的数据。
注意:扩充或者缩放的内存单元是新开辟的内存单元这个过程中有值的拷贝过程。返回值是新开辟的地址空间首地址
四:静态内存和动态内存的比较
静態开辟的内存:在栈中开辟,由编译器分配由系统自动释放
动态开辟的内存:在堆中开辟,由程序员开辟由程序员自动释放。
五:跨函数使用内存的问题
发表您的学习评价或疑问 (可以獲得虎课币哦)
为课程评分: 请选择课程评分
难易度程度: 太简单简单适中有点难太难了请选择课程难易程度(+5虎课币)