ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

memcpy的模拟实现

memcpy的模拟实现

目录

摘要:

一:memcpy的使用

1:完整复制整形数组

2:部分复制整形数组

3:完整复制字符数组

4:部分复制字符数组

二:memcpy的实现


​​​​​​​

摘要:

本文介绍并实现memcpy~


一:memcpy的使用

函数原型:

void * memcpy ( void * destination, const void * source, size_t num );

参数解释:

  • dest:目标内存地址的指针,即复制后的数据存放位置。

  • src:源内存地址的指针,即要被复制的数据来源。

  • n:要复制的字节数。

函数功能:

将数据从src指向的内存区域复制n个字节到dest指向的内存区域。

  • 按字节逐一复制。

  • 不会在复制的时候遇到\0而停止(与字符串函数strcpy不同)。

  • 适用于任意数据类型(int、float、结构体、数组等)。

返回值:

返回dest的指针(即目标内存区域的首地址)。

注意事项:

①:内存区域不能重叠,重叠则必须使用memmove

⚠️:对于重叠,谨记使用memmove!某些编译器上memcpy也可以处理重叠的,比如vs,但不意味着所有编译器的memcpy上都可以实现重叠拷贝!所以我们模拟实现memcpy的时候,也只需要针对不重叠的情况去实现。

②:复制'\0'不会停止,因为memcpy完全按字节复制,不关心内容

⚠️:所以对于字符数组来说,如果复制的内容没有包含'\0'结束符,则需要自己手动加上

使用示例:

1:完整复制整形数组

#include <stdio.h> #include <string.h> int main() { int src[] = {1, 2, 3, 4, 5}; int dest[5]; memcpy(dest, src, sizeof(src)); printf("整型数组完整复制:\n"); for (int i = 0; i < 5; i++) { printf("%d ", dest[i]); } printf("\n"); return 0; }

解释:sizeof(src)计算的就是src这个被复制的数组的大小字节数

2:部分复制整形数组

#include <stdio.h> #include <string.h> int main() { int src[] = { 10, 20, 30, 40, 50 }; int dest[5] = { 0 }; memcpy(dest, src, 3 * sizeof(int)); printf("整型数组部分复制(只复制前3个):\n"); for (int i = 0; i < 5; i++) { printf("%d ", dest[i]); } printf("\n"); return 0; }

解释:对部分复制,往往采取sizeof计算出单个元素类型的大小,然后乘上数目

3:完整复制字符数组

#include <stdio.h> #include <string.h> int main() { char src[] = "Hello"; char dest[10]; memcpy(dest, src, strlen(src) + 1); printf("字符数组完整复制:\n"); printf("%s\n", dest); return 0; }

解释:对于"Hello"来说strlen(src)返回值为5,但我们需要+1去把'\0'也复制

4:部分复制字符数组

#include <stdio.h> #include <string.h> int main() { char src[] = "Hello"; char dest[10]; memcpy(dest, src, 3); dest[3] = '\0'; printf("字符数组部分复制(只复制前3个,手动加结束符):\n"); printf("%s\n", dest); return 0; }

解释:对于字符数组的部分复制,我们往往会在dest数组后面手动置'\0'


二:memcpy的实现

void * memcpy ( void * destination, const void * source, size_t num );

两个参数的类型都是void *,是因为memcpy身为一个内存函数,是以字节为单位进行操作的,所以适配于很多类型,不知道传过来的是什么类型,所以用void *接收,内部再强转为char*以字节为单位进行操作即可;而const修饰source代表不会对被复制的内存进行修改!

所以我们模拟实现的思路就是强转为char*之后然后进行num次的逐字节复制

代码:

#include <assert.h> void *my_memcpy(void *dst, const void *src, size_t count) { void *ret = dst; // 保存原地址,用于返回 assert(dst && src); // 断言非空 while (count--) { *(char *)dst = *(char *)src; // 逐字节复制 dst = (char *)dst + 1; // 指针后移1字节 src = (char *)src + 1; } return ret; }

解释:

①:首先 肯定是需要用ret保存一下dst指针的,用于最后的返回,因为dst会在后面的代码中改变

②:断言检测dst和src指针,其一为空,则代表用于传参错误,直接报错

③:以count为循环次数,在while循环的内部将dst和src强转为char*进行逐字节的复制

📌 [ 作者 ] shylyly
📃 [ 首次发布 ] 2024.3.20
❌ [ 最新修改 ] 2026.10.14
📜 [ 声明 ] 由于笔者水平有限,文中难免有疏漏或不妥之处,还望读者不吝赐教。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进