C语言内存管理函数
面试里会遇到让自己编写一个内存管理函数
1. memset
将指定的内存区域的每个字节设置为指定的值
函数原型:
void *memset(void *s, int c, size_t n);
- 参数:
s
: 指向要填充的内存块的指针。c
: 要设置的值(会被转换为无符号字符)。n
: 要设置的字节数。
- 用途: 常用于初始化数组或清空内存,例如将一个数组的所有元素设置为 0。
- 示例:
int arr[5];
memset(arr, 0, sizeof(arr)); // 将 arr 的所有元素设置为 0
自己编写:
void *my_memset(void *s, int c, size_t n) {
unsigned char *p = s; // 将 void* 转换为 unsigned char*
while (n--) {
*p++ = (unsigned char)c; // 设置每个字节
}
return s; // 返回原始指针
}
2. memcpy
用于复制源内存到目标内存。
- 函数原型:
void *memcpy(void *dest, const void *src, size_t n);
- 参数:
dest
: 指向目标内存区域的指针(将数据复制到这里)。src
: 指向源内存区域的指针(从这里复制数据)。n
: 要复制的字节数。
示例
int src[5] = {1, 2, 3, 4, 5};
int dest[5];
memcpy(dest, src, sizeof(src)); // 将 src 的内容复制到 dest
自己编写
void *my_memcpy(void *dest, const void *src, size_t n) {
unsigned char *d = dest; // 目标指针
const unsigned char *s = src; // 源指针
while (n--) {
*d++ = *s++; // 逐个字节复制
}
return dest; // 返回目标指针
}
3. memmove
用于从一个内存区域复制数据到另一个内存区域,支持内存重叠。
函数原型:
int memcmp(const void *s1, const void *s2, size_t n);
自己编写
void *my_memmove(void *dest, const void *src, size_t n) {
unsigned char *d = dest;
const unsigned char *s = src;
if (d < s) {
// 正常复制
while (n--) {
*d++ = *s++;
}
} else {
// 从后向前复制
d += n;
s += n;
while (n--) {
*(--d) = *(--s);
}
}
return dest;
}
4. memcmp
比较两个内存块的内容。
int my_memcmp(const void *s1, const void *s2, size_t n) {
const unsigned char *p1 = s1;
const unsigned char *p2 = s2;
while (n--) {
if (*p1 != *p2) {
return *p1 - *p2; // 返回两个不同字节的差
}
p1++;
p2++;
}
return 0; // 相等
}
5. malloc
会请求操作系统分配一定量的内存。一般实现比较复杂,这里给出一个非常简化的版本。
void *my_malloc(size_t size) {
void *ptr = sbrk(size); // 使用 sbrk 请求内存(仅用于示例,真实情况下更复杂)
return (ptr == (void *)-1) ? NULL : ptr; // 错误处理
}
6. free
用于释放先前分配的内存。
void my_free(void *ptr) {
// 这里通常需要将指针返回内存管理系统
// 真实情况下,这需要维护一个内存块的链表或其他结构
}
7. realloc
是调整动态内存块的大小,通常会先调用 malloc
和 memcpy
。
void *my_realloc(void *ptr, size_t size) {
if (ptr == NULL) {
return my_malloc(size); // 如果原指针为 NULL,分配新内存
}
// 获取原内存块的大小(具体实现中可能需要额外存储大小)
size_t old_size = /* ... */;
void *new_ptr = my_malloc(size);
if (new_ptr) {
my_memcpy(new_ptr, ptr, old_size < size ? old_size : size);
my_free(ptr); // 释放旧内存
}
return new_ptr; // 返回新指针
}