C语言内存函数完全指南:memcpy/memmove/memset/memcmp
除了字符串操作,C标准库还提供了一系列直接操作内存块的函数。这些函数以字节为单位处理数据,能够高效地拷贝、移动、设置和比较任意类型的内存块。本文将详细讲解
memcpy、memmove、memset、memcmp的用法、区别及模拟实现,帮助读者安全灵活地操纵内存。
目录

一、memcpy的使用和模拟实现
void *memcpy(void *destination, const void *source, size_t num);
- 从
source位置向后复制num个字节到destination。 - 不会因为遇到
'\0'而停止,完全按字节数操作。 - 如果源和目标内存区域重叠 ,行为未定义(应使用
memmove)。
示例:拷贝整型数组的前5个元素(20字节)
c
#include <stdio.h>
#include <string.h>
int main() {
int arr1[] = {1,2,3,4,5,6,7,8,9,10};
int arr2[10] = {0};
memcpy(arr2, arr1, 20); // 拷贝20字节(5个int)
for (int i = 0; i < 10; i++)
printf("%d ", arr2[i]); // 1 2 3 4 5 0 0 0 0 0
return 0;
}
模拟实现:
c
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;
src = (char*)src + 1;
}
return ret;
}
关键 :使用 char* 指针逐字节拷贝,保证通用性。

二、memmove的使用和模拟实现
void *memmove(void *destination, const void *source, size_t num);
- 功能与
memcpy类似,但允许源和目标内存重叠。 - 当无法确定是否重叠时,应优先使用
memmove。
示例:将数组前5个元素移动到从下标2开始的位置
c
int arr[] = {1,2,3,4,5,6,7,8,9,10};
memmove(arr+2, arr, 20); // 重叠拷贝
// 结果:1 2 1 2 3 4 5 8 9 10
模拟实现(需考虑拷贝方向):
- 若目标地址在源地址之前,从前往后拷贝。
- 若目标地址在源地址之后且重叠,从后往前拷贝。
c
void *my_memmove(void *dst, const void *src, size_t count) {
void *ret = dst;
assert(dst && src);
if (dst <= src || (char*)dst >= (char*)src + count) {
// 非重叠或目标在前:从前向后拷贝
while (count--) {
*(char*)dst = *(char*)src;
dst = (char*)dst + 1;
src = (char*)src + 1;
}
} else {
// 重叠且目标在后:从后向前拷贝
dst = (char*)dst + count - 1;
src = (char*)src + count - 1;
while (count--) {
*(char*)dst = *(char*)src;
dst = (char*)dst - 1;
src = (char*)src - 1;
}
}
return ret;
}
三、memset函数的使用
void *memset(void *ptr, int value, size_t num);
- 将
ptr指向的内存块的前num个字节每个字节 设置为value(value转为unsigned char后填充)。 - 常用于数组或结构体的快速初始化。
示例 :将字符串前6个字符改为 'x'
c
char str[] = "hello world";
memset(str, 'x', 6);
printf("%s\n", str); // "xxxxx world"
注意 :memset 以字节为单位,不能用于将整型数组全部设为 1(因为会变成 0x01010101),除非值为 0。
c
int arr[10];
memset(arr, 0, sizeof(arr)); // 正确,全部置0
memset(arr, 1, sizeof(arr)); // 每个字节变1,整型值变为 0x01010101
四、memcmp函数的使用
int memcmp(const void *ptr1, const void *ptr2, size_t num);
- 比较
ptr1和ptr2指向的内存块的前num个字节。 - 返回值与
strcmp类似:<0:ptr1 的字节值小于 ptr20:相等>0:ptr1 的字节值大于 ptr2
示例:比较两个字符串(区分大小写)
c
char buf1[] = "DWgaOtP12df0";
char buf2[] = "DWGAOTP12DF0";
int n = memcmp(buf1, buf2, sizeof(buf1));
if (n > 0)
printf("%s is greater than %s\n", buf1, buf2);
else if (n < 0)
printf("%s is less than %s\n", buf1, buf2);
else
printf("equal\n");
注意 :memcmp 比较的是原始字节值(按 unsigned char 比较),而不是字符串语义,不会因为 '\0' 提前停止。
总结:内存函数以字节为单位操作内存,适用于任何数据类型。
memcpy高效但不能重叠拷贝;memmove支持重叠,更安全;memset快速填充字节;memcmp比较内存块。掌握这些函数并理解其模拟实现,能够有效处理数组、结构体等内存块,提升代码性能和可靠性。特别注意memset的字节填充特性及memmove的方向处理。