目录
[一. memcpy的使用和模拟实现](#一. memcpy的使用和模拟实现)
[1.1 memcpy函数理解](#1.1 memcpy函数理解)
[1.2 memcpy使用示例](#1.2 memcpy使用示例)
[1.3 memcpy模拟实现](#1.3 memcpy模拟实现)
[二. memmove使用和模拟实现](#二. memmove使用和模拟实现)
[2.1 memove函数理解](#2.1 memove函数理解)
[2.2 memove使用示例](#2.2 memove使用示例)
[2.3 memmove vs memcpy](#2.3 memmove vs memcpy)
[2.4 memmove函数模拟实现](#2.4 memmove函数模拟实现)
[三. memset函数的使用](#三. memset函数的使用)
[3.1 memset函数理解](#3.1 memset函数理解)
[3.1 memset使用示例](#3.1 memset使用示例)
[四. memcmp函数的使用](#四. memcmp函数的使用)
[4.1 memcmp 函数理解](#4.1 memcmp 函数理解)
[4.2 memcmp使用示例](#4.2 memcmp使用示例)
一. memcpy的使用和模拟实现
1.1 memcpy函数理解
memcpy
是 C 标准库(<string.h>
)中的一个函数,用于按字节复制内存块。它的原型如下:
cpp
void *memcpy(void *dest, const void *src, size_t n);
参数说明
参数 | 类型 | 说明 |
---|---|---|
dest |
void* |
目标内存地址(复制到哪) |
src |
const void* |
源内存地址(从哪复制) |
n |
size_t |
要复制的字节数 |
返回值
- 返回
dest
的指针(即目标内存地址)。
memcpy
的特点
不检查重叠(Undefined Behavior if Overlapping)
如果
src
和dest
的内存区域重叠 ,行为是未定义的(UB),可能导致数据错误。如果可能重叠,应该使用
memmove
(它会正确处理重叠情况)。按字节复制
- 不管数据类型(
int
、char
、结构体等),直接按字节复制。不关心
'\0'
(与strcpy
不同)
strcpy
遇到'\0'
停止,而memcpy
严格复制n
个字节。
1.2 memcpy使用示例
1. 复制数组
cpp
#include <stdio.h>
#include <string.h>
int main() {
int src[5] = {1, 2, 3, 4, 5};
int dest[5];
memcpy(dest, src, sizeof(src)); // 复制整个数组
for (int i = 0; i < 5; i++) {
printf("%d ", dest[i]); // 输出:1 2 3 4 5
}
return 0;
}

2. 复制结构体
cpp
#include <stdio.h>
#include <string.h>
typedef struct {
int id;
char name[20];
} Person;
int main() {
Person p1 = {1, "Alice"};
Person p2;
memcpy(&p2, &p1, sizeof(Person)); // 复制整个结构体
printf("ID: %d, Name: %s\n", p2.id, p2.name); // 输出:ID: 1, Name: Alice
return 0;
}
1.3 memcpy模拟实现
cpp
#include<stdio.h>
#include<string.h>
#include<assert.h>
void* my_memcpy(void* dest, const void* source, size_t num)
{
// 断言检查:确保 dest 和 source 不是 NULL
assert(dest && source);
// 保存目标地址的起始位置,用于返回
void* ret = dest;
// 逐字节复制,共复制 num 个字节
while (num--)
{
// 将 source 的当前字节复制到 dest
*(char*)dest = *(char*)source;
// 移动 dest 和 source 指针到下一个字节
dest = (char*)dest + 1;
source = (char*)source + 1;
}
// 返回目标内存的起始地址
return ret;
}
int main()
{
int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[20];
my_memcpy(arr2, arr1, 40);
int i = 0;
for (i = 0;i < 10;i++)
{
printf("%d ", arr2[i]);
}
return 0;
}
二. memmove使用和模拟实现
2.1 memove函数理解
memmove
是 C 标准库(<string.h>
)中的一个函数,用于安全地复制内存块,即使源内存和目标内存有重叠也能正确处理。它的原型如下:
cpp
void *memmove(void *dest, const void *src, size_t n);
参数说明
参数 | 类型 | 说明 |
---|---|---|
dest |
void* |
目标内存地址(复制到哪) |
src |
const void* |
源内存地址(从哪复制) |
n |
size_t |
要复制的字节数 |
返回值
- 返回
dest
的指针(即目标内存地址)。
memmove
的特点
正确处理内存重叠
如果
src
和dest
的内存区域重叠 ,memmove
会确保数据正确复制(不会像memcpy
那样出现未定义行为)。实现方式:检查内存重叠情况,决定是从前往后复制还是从后往前复制。
按字节复制
- 不管数据类型(
int
、char
、结构体等),直接按字节复制。不关心
'\0'
(与strcpy
不同)
strcpy
遇到'\0'
停止,而memmove
严格复制n
个字节。
2.2 memove使用示例
cpp
#include <stdio.h>
#include <string.h>
int main() {
char str[] = "Hello, World!";
// 把 "World!" 移动到前面(src 和 dest 重叠)
memmove(str, str + 7, 6); // 正确
// memcpy(str, str + 7, 6); // ❌ 未定义行为(UB)
printf("%s\n", str); // 输出:World! World!
return 0;
}

2.3 memmove
vs memcpy
函数 | 是否处理重叠 | 速度 | 适用场景 |
---|---|---|---|
memcpy |
❌ 不处理(UB) | ⚡ 更快 | 确定不重叠时使用 |
memmove |
✅ 安全处理 | 🐢 稍慢 | 可能重叠时使用 |
memmove
的实现原理
memmove
的底层实现通常会检查内存是否重叠:
如果
dest < src
:从前往后复制(避免覆盖未复制的数据)。如果
dest > src
:从后往前复制(避免覆盖未复制的数据)。
2.4 memmove函数模拟实现
cpp
#include<stdio.h> // 标准输入输出头文件
#include<assert.h> // 断言头文件,用于调试检查
// 自定义的内存移动函数,功能类似于标准库的memmove
// 参数:
// dest - 目标内存地址
// src - 源内存地址
// num - 要移动的字节数
// 返回值:返回目标内存地址
void* my_memmove(void* dest, const void* src, size_t num)
{
// 使用断言确保dest和src都不是空指针
assert(dest && src);
// 保存目标地址的原始值,用于返回
void* ret = dest;
// 判断目标地址是否在源地址之前
if (dest < src)
{
// 从前向后拷贝(适用于目标地址在源地址之前的情况)
while (num--)
{
// 逐字节拷贝
*(char*)dest = *(char*)src;
// 移动指针到下一个字节
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
else
{
// 从后向前拷贝(适用于目标地址在源地址之后的情况)
// 这样可以防止重叠区域被覆盖
while (num--)
{
// 从末尾开始拷贝
*((char*)dest + num) = *((char*)src + num);
}
}
// 返回目标地址
return ret;
}
int main()
{
// 测试数组
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
// 调用my_memmove函数:
// 将arr+2开始的20个字节(即5个int)移动到arr开始的位置
// 相当于把3,4,5,6,7移动到1,2,3,4,5的位置
my_memmove(arr, arr + 2, 20);
// 打印移动后的数组
for (int i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
关键实现细节
- 通过比较
dest
和src
的地址决定拷贝方向- 当
dest < src
时,从前向后拷贝(避免覆盖未拷贝的数据)- 否则,从后向前拷贝(同样是为了避免数据覆盖问题)
- 使用
char*
指针进行逐字节操作
三. memset函数的使用
3.1 memset函数理解
memset
是 C/C++ 标准库中的一个内存操作函数,用于将一块内存区域填充为指定的值。
函数原型
cpp
void *memset(void *ptr, int value, size_t num);
参数说明
-
ptr
: 指向要填充的内存块的指针 -
value
: 要设置的值(以 int 形式传递,但实际使用时会被转换为 unsigned char) -
num
: 要填充的字节数
功能
memset
将从 ptr
开始的内存区域的前 num
个字节都设置为 value
的值。
常见用途
-
初始化数组为0:
cppint arr[100]; memset(arr, 0, sizeof(arr));
-
初始化结构体:
cppstruct MyStruct s; memset(&s, 0, sizeof(s));
3.1 memset使用示例
cpp
#include <stdio.h>
#include <string.h>
int main()
{
char str[] = "hello world";
memset(str, 'C', 6);
printf(str);
return 0;
}

我们来看下面这一串代码,判断能不能将arr的每个元素设置为1
cpp
int main()
{
int arr1[] = { 0 };
memset(arr1, 1, 40);
return 0;
}
结果是不行,但是可以把一个数组里的都设置为0;
四. memcmp函数的使用
4.1 memcmp 函数理解
memcmp
是 C/C++ 标准库中的一个内存比较函数,用于比较两块内存区域的内容。
函数原型
cpp
int memcmp(const void *ptr1, const void *ptr2, size_t num);
参数说明
ptr1
: 指向第一个内存块的指针
ptr2
: 指向第二个内存块的指针
num
: 要比较的字节数
返回值
负数 :
ptr1
小于ptr2
(按字典序)0 :
ptr1
和ptr2
相等正数 :
ptr1
大于ptr2
(按字典序)
功能
memcmp
逐字节比较 ptr1
和 ptr2
指向的内存区域的前 num
个字节,直到发现不匹配的字节或比较完所有字节。
常见用途
-
比较数组内容:
cppint arr1[5] = {1, 2, 3, 4, 5}; int arr2[5] = {1, 2, 3, 4, 5}; if (memcmp(arr1, arr2, sizeof(arr1)) == 0) { printf("Arrays are equal\n"); }
-
比较结构体:
cppstruct Point { int x; int y; }; struct Point p1 = {1, 2}; struct Point p2 = {1, 2}; if (memcmp(&p1, &p2, sizeof(struct Point)) == 0) { printf("Points are equal\n"); }
-
比较字符串(不依赖null终止符):
cppchar str1[10] = "hello"; char str2[10] = "hello"; if (memcmp(str1, str2, 5) == 0) { printf("First 5 chars are equal\n"); }
与 strcmp 的区别
特性 | memcmp | strcmp |
---|---|---|
比较方式 | 比较指定字节数 | 比较到遇到null终止符 |
安全性 | 更安全(指定长度) | 需要确保字符串有终止符 |
性能 | 通常更快 | 需要检查每个字符是否为终止符 |
用途 | 任意内存区域比较 | 仅用于字符串比较 |
4.2 memcmp使用示例
cpp
#include <stdio.h>
#include <string.h>
int main()
{
char buffer1[] = "ABCDEFG";
char buffer2[] = "LOVEYOU";
int n;
n = memcmp(buffer1, buffer2, sizeof(buffer1));
if (n > 0)
printf("'%s' is greater than '%s'.\n", buffer1, buffer2);
else if (n < 0)
printf("'%s' is less than '%s'.\n", buffer1, buffer2);
else
printf("'%s' is the same as '%s'.\n", buffer1, buffer2);
return 0;
}

结语:本篇文章内容就到此结束,继前面一篇文章后,在此篇文章中给大家继续分享了C语言内存函数中memcpy和memmove的使用和模拟实现,memset函数的使用,memcmp函数的使用等知识点,后续会继续给分享其它内容,如果文章对你有帮助的话,欢迎评论,点赞,收藏加关注,感谢大家的支持。
往期回顾:
《C 语言字符串操作从入门到实战(上篇):字符分类、转换及strlen/strcpy等函数详解》
《C 语言字符串操作从入门到实战(下篇):strncpy/strncat/strstr 等函数原理与实现》