
目录摘要一memmove的使用1不重叠2 重叠情况13 重叠情况2二memmove的实现1情况分析2规律总结3实现代码摘要本文介绍并实现memmove~一memmove的使用void * memmove ( void * destination, const void * source, size_t num );参数解释dest目标内存地址的指针数据要复制到的位置src源内存地址的指针数据来源的位置n要复制的字节数函数功能将src指向的内存区域中的n个字节复制到dest指向的内存区域。返回值返回dest的指针目标内存区域的首地址注意事项①主要用于内存重叠场景当dest和src有重叠时memmove是安全的选择②性能略低于memcpy因为memmove需要判断是否重叠可能牺牲少量性能不重叠时优先用memcpy重叠时用memmove使用示例1不重叠#include stdio.h #include string.h int main() { int src[] {1, 2, 3, 4, 5}; int dest[5]; memmove(dest, src, sizeof(src)); printf(整型数组不重叠复制); for (int i 0; i 5; i) printf(%d , dest[i]); printf(\n); return 0; }解释不重叠的情况下是等同于memcpy的2 重叠情况1#include stdio.h #include string.h int main() { int arr[] { 10, 20, 30, 40, 50 }; // 将 [30,40,50] 移动到 [10,20,30] 的位置 memmove(arr, arr 2, 3 * sizeof(int)); printf(整型数组向左重叠移动); for (int i 0; i 5; i) printf(%d , arr[i]); printf(\n); return 0; }解释重叠情况1就是指针src 小于 指针desr memmove可以应对3 重叠情况2#include stdio.h #include string.h int main() { int arr[] { 10, 20, 30, 40, 50 }; // 将 [10,20,30] 移动到 [20,30,40] 的位置 memmove(arr 2, arr, 3 * sizeof(int)); printf(整型数组向右重叠移动); for (int i 0; i 5; i) printf(%d , arr[i]); printf(\n); return 0; }解释重叠情况2就是指针src 大于 指针desr memmove也可以应对二memmove的实现void * memmove ( void * destination, const void * source, size_t num );对于不重叠的情况我们不需要去讨论src和dest的大小关系都可以直接复制我们知道复制的方式无非就是从前往后复制 或 从后往前复制 这两种方法对于重叠的情况则需要根据src和dest的大小关系分开讨论寻找适配的复制方法1情况分析asrc 大于 dest解释当src 大于 dest的时候如果对src部分从后往前复值则一定出错按照8,7,6,5,4的顺序复制给5,4,3,2,1无法得到4,5,6,7,8,6,7,8,9,10正确而是得到7,8,6,7,8,6,7,8,9,10错误而从前往后赋值则正确bsrc 小于 dest解释当src 小于 dest的时候若是从前往后复制就是按照4,5,6,7,8的顺序复制给6,7,8,9,10无法得到1,2,3,4,5,4,5,6,7,8(正确)而是得到1,2,3,4,5,4,5,4,5,4错误而从后往前赋值则正确2规律总结总结①重叠情况若srcdest则从前往后进行复制若srcdest则从后往前复制②不重叠情况则任意选择③统一 srcdest前往后复制srcdest后往前复制更深层次的理解当src(源)dest(目的)的时候只能后往前因为src后部分和dest的前部分重叠此时采取错误的前往后拷贝则会让src后部分还没被拷贝的元素被更新赋值了等到之后要拷贝src后部分的元素则肯定错当src(源)dest(目的)的时候只能前往后因为src前部分和dest的后部分重叠此时采取错误的后往前拷贝则会让src前部分还没被拷贝的元素被更新赋值了等到之后要拷贝src前部分的元素则肯定错3实现代码#include assert.h void *my_memmove(void *dest, const void *src, size_t num) { void *ret dest; assert(dest src); if (src dest) { // 内存不重叠或 dest 在前从前往后复制 while (num--) { *(char *)dest *(char *)src; dest (char *)dest 1; src (char *)src 1; } } else { // 内存重叠且 dest 在后从后往前复制 while (num--) { *((char *)dest num) *((char *)src num); } } return ret; }解释①首先 肯定是需要用ret保存一下dst指针的用于最后的返回因为dst会在后面的代码中改变②断言检测dst和src指针其一为空则代表用于传参错误直接报错③判断情况若为src dest 则采用前往后复制esle采取后往前复制④前往后复制就是类似memcpy的强转为char*之后直接num次循环逐字节复制而后往前复制则强转char*之后需要让指针取指向最后一个元素的最后一个字节然后往前逐字节复制而while (num--)这一步不仅循环了num次控制次数并且让num在第一个进入循环就减1了此时直接让强转为char*的指针num即可指向最后一个元素的最后一个字节 [ 作者 ] shylyly [ 首次发布 ] 2024.3.20❌ [ 最新修改 ] 2026.10.14 [ 声明 ] 由于笔者水平有限文中难免有疏漏或不妥之处还望读者不吝赐教。