内存管理的库函数介绍
内存管理函数(<string.h>)
内存初始化/赋值(memset)
memset
- 函数原型:
void *memset( void *dest, int val, size_t count ); - 功能:把dest指针后的count字节的空间,设置为值val
注:memset是以Byte为单位的
- 函数原型:
内存复制/拷贝(memcpy、memmove)
memcpy
- 函数原型:
void *memcpy( void *dest, const void *src, size_t count ); - 功能:把src后的count字节的内容,从dest地址开始拷贝一份
- 注意事项:
- 若有重复的区间,则需要考虑从前拷贝/从后拷贝来避免(不推荐有重复区间使用memcpy)
- 若要使用安全的函数,则考虑memmove
- 函数原型:
memmove
函数原型:
errno_t memmove_s(void *dest, rsize_t destsz, const void *src, rsize_t count);(c11起)功能:从 src 所指向的对象复制 count 个字节到 dest 所指向的对象。两个对象都被转译成 unsigned char 的数组。对象可以重叠:如同复制字符到临时数组,再从该数组到 dest 一般进行复制
返回 dest 的副本(临时内存地址),当然更有意义的是 dest 本身
注意事项:
- 若 dest 所指向的字符数组大小 < count <= destsz 则行为未定义
内存比较(memcmp)
- memcmp
- 函数原型:
int memcmp( const void* lhs, const void* rhs, size_t count ); - 功能:比较两个地址后count字节的内容,若相同则返回0
- 函数原型:
- memcmp
动态内存管理函数(stdlib.h)
数据的初始化有以下几种情况:
数据在栈空间开辟
特点:创建时,未初始化,且为随机值
应用场景:局部变量、函数创建时开辟堆栈帧
数据在堆空间开辟
特点:创建时,未初始化,且为随机值
应用场景:动态内存管理
数据在静态区开辟
特点:创建时,数据就已初始化为0
应用场景:全局变量、函数地址、static修饰的局部变量

动态内存的开辟/释放
malloc函数原型:
void *malloc( size_t size );功能:在堆区开辟 size 字节大小的空间,并返回地址
注:
malloc(0)的行为是未定义的若开辟失败,malloc则会返回空指针,失败后可以使用 strerror 函数(参阅字符串库函数)打印错误信息
返回值需要使用强制类型转化来使用
若要初始化为0,建议用下面这种语法
#include <stdlib.h> #include <string.h> int main() { void* ptr = malloc(3); memset(ptr, 0, 3); free(ptr); return 0; }
calloc- 函数原型:
void* calloc( size_t num, size_t size ); - 功能:在堆区开辟 num 个对象,每个对象 size 字节大小,并返回地址
注:
- 因为对齐需求的缘故,分配字节数不必等于
num*size - 与 malloc 不同,calloc会初始化内存为0!
- 使用calloc可以很方便开辟一个数组,如
int* arr = (int*)calloc(10, sizeof(int));
- 函数原型:
free- 函数原型:
void free( void *ptr ); - 功能:把 ptr 指针进行解分配
注:
- 在使用free后,记得把不用的指针置为NULL(别死皮赖脸,记住人家的地址)
- 使用时,和 开辟函数 组合使用,做到 “谁开辟谁释放”,写开辟时就写好释放
- 函数原型:
realloc- 函数原型:
void *realloc( void *ptr, size_t new_size ); - 功能:调整动态开辟的内存空间 ptr 的大小为 new_size
注:
- 如果原空间后面的内存空间足够追加,则realloc会在后面追加空间
- 如果原空间后面的内存空间不足以追加,则会开辟一块新空间,把旧数据拷贝到新空间上面,并释放旧的空间
- 若空间不够用,开辟失败则会返回NULL
- 若传递的指针为空指针,则与malloc功能相同
- 因为有可能改变地址,所以重新开辟后需要判空,再重新赋给记录地址的指针变量!
- 函数原型: