C语言内存函数详解:memcpy、memmove、memset与memcmp

C语言内存函数详解

1. memcpy

1
void *memcpy(void *dest, const void *src, size_t count);

复制 count 个字节,适合两个不重叠的内存区域。

1
2
3
int source[] = {1, 2, 3, 4, 5};
int target[5];
memcpy(target, source, sizeof(source));

模拟实现:

1
2
3
4
5
6
7
8
9
void *my_memcpy(void *dest, const void *src, size_t count)
{
unsigned char *d = dest;
const unsigned char *s = src;
void *result = dest;
while (count--)
*d++ = *s++;
return result;
}

2. memmove

memmove 支持源和目标区域重叠。目标在源后方且重叠时,应从后往前复制,否则从前往后复制。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void *my_memmove(void *dest, const void *src, size_t count)
{
unsigned char *d = dest;
const unsigned char *s = src;
void *result = dest;

if (d < s)
while (count--) *d++ = *s++;
else if (d > s)
{
d += count;
s += count;
while (count--) *--d = *--s;
}
return result;
}

示例:

1
2
int arr[] = {1, 2, 3, 4, 5};
memmove(arr + 1, arr, 4 * sizeof(int));

3. memset

memset 按字节设置内存:

1
2
char buffer[128];
memset(buffer, 0, sizeof(buffer));

不要用 memset(arr, 1, sizeof(arr)) 把 int 数组设置为1。每个字节都会变为 0x01,一个32位 int 通常得到 0x01010101。

4. memcmp

memcmp 按无符号字节逐个比较:

1
int result = memcmp(data1, data2, length);

返回值小于0、等于0或大于0。它适合比较原始字节序列,但不适合直接判断含填充字节的结构体是否“逻辑相等”,填充字节可能是不确定值。

5. 字符串函数与内存函数

类型 结束依据 能否处理任意对象
strcpy/strcmp \0 主要处理字符串
memcpy/memcmp 显式字节数 可以处理任意对象表示

内存函数不知道数据类型与字符串结束位置,调用者必须给出正确字节数。

6. 易错点

  • 把元素个数误当成字节数;
  • 对重叠区域使用 memcpy;
  • 源或目标空间不足;
  • 对含指针成员的对象进行浅拷贝后误以为完成深拷贝;
  • 用 memcmp 比较浮点值或含填充的结构体逻辑等价性。

7. 总结

内存函数是无类型的字节工具。选择 memcpy 还是 memmove,关键看区域是否可能重叠;使用 memset 时,必须牢记它写入的是单个字节值。