1. 传统数组的问题
指针和动态内存分配是C语言中最重要的两个部分。在C语言中,对内存的管理至关重要。
传统数组占用的内存在定义的那一刻已经被定死了。
如果没有动态内存分配,可能会出现为了满足最大需求而浪费内存的情况。例如,有极少部分用户需要输入很长的数据时,需要为了这部分用户扩大变量所占用的内存,而对于大多数用户来说,这样显然会浪费很多内存空间。
因此以往传统的数组定义形式灵活性低,应用受限。整个程序都依赖于预设编译前的大小,可能不够用,也可能会浪费,内存不够用时可能会有内存溢出,导致一些安全隐患。
这时候就需要动态内存分配,可以处理可变大小的数据,有高效的数据结构和资源优化。
2. ★重点:栈内存和堆内存的对比
计算机操作系统的内存管理机制中,有两种不同的存储区域:栈内存(Stack Memory)与堆内存(Heap Memory)。
这两种内存的不同点包括:分配机制、生命周期、访问速度、用途区分。
栈内存:
- 有自动管理机制,函数调用时候,局部变量会被分配在栈上,当函数返回时候,局部变量全部销毁释放。
- 栈内存在编译时候就已经确定好了需要分配的内存空间大小。
- 栈内存的分配和访问速度通常要比堆内存快,它是一种线性的数据结构。
- 大小有限制,栈的大小在程序启动那一刹那就已经确定,无法改动。如果栈的内存空间被耗尽,就意味着崩溃(栈溢出)。
- 一般用于存储函数的局部变量,函数参数,函数调用的返回地址。
堆内存:
- 需要动态(手动)管理,调用操作内存空间相关函数来手动控制内存的分配与释放。例如,
malloc、calloc、realloc、free。 - 速度相较于栈有点慢,它需要在内存中寻找足够大的连续空间块。
- 大小灵活,堆的大小通常受到可用系统内存的限制,而非栈本身的限制。它能够支持动态按需分配大量内存。
3. malloc函数动态内存分配的使用与释放
malloc函数传入一个size_t类型的数据,表示要分配的内存大小,单位是字节。返回一个void*类型的指针,在C语言中用于泛型编程,可以转换为任意其他数据类型的指针。
malloc函数分配的内存在堆上。
malloc函数包含在头文件stdlib.h中。
1 |
|
4. 企业案例:realloc函数与释放
realloc函数用来动态调整已经被分配的内存空间。
参数:
ptr:指针指向一个要重新分配内存的内存块,该内存块之前是通过调用malloc、calloc或realloc进行分配内存的。如果之前未被分配,为空指针,则会分配一个新的内存块,且函数返回一个指向它的指针。size:内存块的新的大小,以字节为单位。如果大小为0,且ptr指向一个已存在的内存块,则ptr所指向的内存块会被释放,并返回一个空指针。
返回值:
- 如果成功,
realloc返回指向新内存块的指针。 - 如果失败,返回
NULL,并且原来的内存块仍然保持不变(并没有释放)。
注意:
realloc可能会将内存块移动到新的位置(如果在原位置没有足够的空间容纳新的大小)。如果移动成功,ptr会指向新位置,旧的内存空间会被释放。需要特别注意,旧的ptr指针需要被更新为realloc返回的新地址。- 如果内存分配失败,
realloc返回NULL,而原始的内存块不会被释放。为避免内存泄漏,应该使用一个临时指针来接收realloc的返回值,并检查是否为NULL。
案例:一个简单的动态调整部门预算的程序。
1 |
|
5. malloc与结构体的使用以及防止内存的泄露
使用malloc函数为一个结构体分配内存时,如果结构体内有成员是指针类型,则需要单独为该成员使用malloc函数分配内存空间。
当使用
malloc函数为一个结构体分配内存时,只分配了结构体本身的空间,包括所有成员变量所占的内存。但如果成员中存在指针,
malloc函数只为指针变量本身分配了空间,但没有为指针指向的数据分配空间。此时指针的值是未定义的(野指针),不能直接使用。
需要再次使用
malloc函数为成员中的指针也分配地址,才可以安全使用,避免了野指针与内存泄露。释放内存时,成员与结构体也需要分别释放。
注意:动态内存的分配一定要进行跟踪和管理,分配内存后,必须立即判断内存是否分配成功,并写好对应的卫语句,在合适的时候释放内存。
下面是一个简单的为结构体及部分成员分配内存的案例。
例如创建一个游戏角色。
1 |
|
6. calloc函数
calloc函数的用法与malloc函数类似,但calloc函数不仅可以分配内存,还同时将所有的位置初始化为0。
下面是一个简单的使用calloc函数为结构体分配内存的案例。
例如为员工创建任务列表。
1 |
|
本文链接: https://hanqingjiang.com/2026/03/10/20260310_C_dynamicMemory/
版权声明: 本作品采用 CC BY-NC-SA 4.0 进行许可。转载请注明出处!
