手动实现 memcpy 函数
手动实现 memcpy 函数
memcpy 函数的核心是按指定字节数复制任意内存数据,实现时需注意:
1. 处理指针类型转换( void* 需强转)
2. 处理内存重叠场景(但标准 memcpy 不要求,此处按非重叠场景实现)
3. 确保复制长度 n 合理
#include <stdio.h>#include <assert.h>#include <string.h> // 用于测试对比// 自定义 memcpy 函数void* my_memcpy(void* dest, const void* src, size_t n) {// 断言:确保目标和源指针非空assert(dest != NULL && src != NULL);// 转换为字符指针,便于逐字节操作char* d = (char*)dest;const char* s = (const char*)src;// 循环复制 n 个字节while (n--) {*d++ = *s++; // 逐字节复制并移动指针}return dest; // 返回目标内存地址}// 测试函数int main() {// 测试1:复制整型数组int arr1[] = {1, 2, 3, 4, 5};int arr2[5] = {0};my_memcpy(arr2, arr1, sizeof(arr1));printf("整型数组复制结果: ");for (int i = 0; i < 5; i++) {printf("%d ", arr2[i]); // 应输出 1 2 3 4 5}printf("\n");// 测试2:复制字符串(含'\0')char str1[] = "Hello";char str2[10] = {0};my_memcpy(str2, str1, strlen(str1) + 1); // +1包含'\0'printf("字符串复制结果: %s\n", str2); // 应输出 Hello// 测试3:复制结构体struct Data {int id;char name[20];};struct Data data1 = {1001, "Test"};struct Data data2;my_memcpy(&data2, &data1, sizeof(struct Data));printf("结构体复制结果: id=%d, name=%s\n", data2.id, data2.name);return 0;}
代码解析
核心逻辑
- 指针类型转换:将 void* 指针转换为 char* ,以便按字节操作(C语言中 char 类型大小为1字节)。
- 逐字节复制:通过 while (n--) 循环复制 n 次,每次复制1字节并移动指针,确保覆盖所有指定字节。
- 返回值:返回 dest 指针,支持链式调用(如 memcpy(a, memcpy(b, c, n), n) )。
与标准库的差异
- 内存重叠处理:标准 memcpy 不要求处理源和目标内存重叠的情况(如 src <= dest && dest < src + n ),若需处理可改用 memmove 。
- 类型安全性:自定义实现通过 void* 兼容所有类型,与标准库行为一致。
安全注意事项
- 调用时需确保 dest 指向的空间足够容纳 n 字节数据,否则会导致内存越界。
- 对于结构体等复杂类型,需确保 n 等于其实际大小(可通过 sizeof 计算)。