C 库函数 - memmove()
memmove() 是 C 语言标准库
单词释义: memmove 是 memory move(内存移动)的缩写,表示在内存中移动数据。
函数描述
C 库函数 void *memmove(void *str1, const void *str2, size_t n) 从 str2 复制 n 个字符到 str1。
与 memcpy() 的区别:
memmove()处理重叠内存区域时更安全。- 如果目标区域和源区域有重叠,
memmove()能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中。 - 如果目标区域与源区域没有重叠,则和
memmove()函数功能相同。
函数声明
下面是 memmove() 函数的声明:
void *memmove(void *str1, const void *str2, size_t n)
参数说明
- str1:指向用于存储复制内容的目标数组,类型强制转换为 void* 指针。
- str2:指向要复制的数据源,类型强制转换为 void* 指针。
- n:要被复制的字节数。
返回值
该函数返回一个指向目标存储区 str1 的指针。
头文件
#include <string.h>
实例
示例 1:基础用法
下面的实例演示了 memmove() 函数的用法:
实例
#include <stdio.h>
#include <string.h>
int main ()
{
// 场景1:非重叠内存拷贝
char dest[] = "oldstring";
char src[] = "newstring";
printf("非重叠拷贝前:dest = %s, src = %s\n", dest, src);
memmove(dest, src, 9);
printf("非重叠拷贝后:dest = %s, src = %s\n", dest, src);
// 场景2:重叠内存拷贝(memmove 优势)
char str[] = "123456789";
printf("\n重叠拷贝前:%s\n", str);
memmove(str + 2, str, 6); // 内存重叠拷贝
printf("重叠拷贝后:%s\n", str);
return 0;
}
#include <string.h>
int main ()
{
// 场景1:非重叠内存拷贝
char dest[] = "oldstring";
char src[] = "newstring";
printf("非重叠拷贝前:dest = %s, src = %s\n", dest, src);
memmove(dest, src, 9);
printf("非重叠拷贝后:dest = %s, src = %s\n", dest, src);
// 场景2:重叠内存拷贝(memmove 优势)
char str[] = "123456789";
printf("\n重叠拷贝前:%s\n", str);
memmove(str + 2, str, 6); // 内存重叠拷贝
printf("重叠拷贝后:%s\n", str);
return 0;
}
运行结果:
非重叠拷贝前:dest = oldstring, src = newstring 非重叠拷贝后:dest = newstring, src = newstring 重叠拷贝前:123456789 重叠拷贝后:121234569
代码解析:
- 定义目标数组
dest和源数组src。 memmove(dest, src, 9)将 src 的前 9 个字符复制到 dest。- 注意:dest 和 src 是独立的数组,这里没有重叠。
示例 2:处理重叠内存
当内存区域重叠时,memmove() 仍能正确处理:
实例
#include <stdio.h>
#include <string.h>
int main()
{
char str[] = "memmove can be very useful";
printf("Before: %s\n", str);
// 从位置 11 开始复制 7 个字符到位置 5 开始的位置
// 这里存在内存重叠
memmove(str + 5, str + 11, 7);
printf("After: %s\n", str);
return 0;
}
#include <string.h>
int main()
{
char str[] = "memmove can be very useful";
printf("Before: %s\n", str);
// 从位置 11 开始复制 7 个字符到位置 5 开始的位置
// 这里存在内存重叠
memmove(str + 5, str + 11, 7);
printf("After: %s\n", str);
return 0;
}
运行结果:
Before: memmove can be very useful After: memvcan bery useful
代码解析:
- 原始字符串:"memmove can be very useful"
- 位置 11 开始是 "can be"(7 个字符)
- 复制到位置 5 开始,结果:"memv" + "can be" + " very useful" = "memvcan be very useful"
- 虽然有重叠,但
memmove()正确处理了这种情况。
示例 3:对比 memcpy 和 memmove
实例
#include <stdio.h>
#include <string.h>
int main()
{
char str1[] = "abcdefghij";
char str2[] = "abcdefghij";
printf("Original: %s\n", str1);
// 使用 memcpy
memcpy(str1 + 2, str1, 5);
printf("memcpy: %s\n", str1);
// 使用 memmove
memmove(str2 + 2, str2, 5);
printf("memmove: %s\n", str2);
return 0;
}
#include <string.h>
int main()
{
char str1[] = "abcdefghij";
char str2[] = "abcdefghij";
printf("Original: %s\n", str1);
// 使用 memcpy
memcpy(str1 + 2, str1, 5);
printf("memcpy: %s\n", str1);
// 使用 memmove
memmove(str2 + 2, str2, 5);
printf("memmove: %s\n", str2);
return 0;
}
运行结果:
Original: abcdefghij memcpy: ababcdfghij memmove: ababcdfghij
说明:在这个简单例子中两者结果相同,但 memmove() 在处理复杂重叠情况时更可靠。
示例 4:复制指定字节数
实例
#include <stdio.h>
#include <string.h>
int main()
{
char src[] = "Hello, World!";
char dest[20];
// 复制前 5 个字符
memmove(dest, src, 5);
dest[5] = '\0'; // 添加字符串结束符
printf("Source: %s\n", src);
printf("Dest: %s\n", dest);
printf("Length: %zu\n", strlen(dest));
return 0;
}
#include <string.h>
int main()
{
char src[] = "Hello, World!";
char dest[20];
// 复制前 5 个字符
memmove(dest, src, 5);
dest[5] = '\0'; // 添加字符串结束符
printf("Source: %s\n", src);
printf("Dest: %s\n", dest);
printf("Length: %zu\n", strlen(dest));
return 0;
}
运行结果:
Source: Hello, World! Dest: Hello Length: 5
代码解析:
memmove(dest, src, 5)只复制前 5 个字符。- 需要手动添加
\0结束符,因为memmove()不会自动添加。
与 memcpy() 的区别
| 特性 | memcpy() | memmove() |
|---|---|---|
| 重叠内存处理 | 未定义,可能出错 | 安全处理重叠区域 |
| 性能 | 可能稍快 | 稍慢(需要额外处理) |
| 使用建议 | 确定无重叠时使用 | 不确定或有重叠时使用 |

C 标准库 - string.h