内存函数:如何使用与模拟实现
专栏:C语言
文章目录
这次我会根据标准C库函数参考,对 memcpy、memmove、memset、memcmp 四个内存操作函数进行标准定义、参数说明、举例以及各自函数的模拟实现。
前言 在C语言编程中,字符串函数仅能处理以
\0结尾的字符数据,适用场景有限。而内存操作函数直接以字节为单位对任意类型数据进行拷贝、移动、赋值与比较,不依赖数据类型、不受结束符限制,是编写通用、高效、底层代码的核心工具。本篇将学习memcpy、memmove、memset、memcmp四大内存函数,从用法、原理到手写模拟实现全覆盖,帮助大家真正掌握内存层面的数据操作逻辑,提升代码的健壮性与编程能力。
一.memcpy -----> 内存块拷贝
1.1函数原型(包含功能,参数,返回值)
函数原型:
void * memcpy ( void * destination, const void * source, size_t num );
功能:
- 从
source指向的内存,向后复制 num 个字节destination指向的内存- 不关心数据类型,只做二进制级别的逐字节拷贝
- 如果两块内存存在重叠时,复制结果为未定义行为
- 头文件:
<string.h>
参数:
destination:目标内存起始地址source:源内存起始地址num:要复制的字节数
返回值:
返回目标内存
destination的起始地址。
1.2举例
#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);
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr2[i]);
}
return 0;
}
🧐分析:先定义两个整型数组,arr1 为源数据,arr2 为目标空间;然后调用 memcpy拷贝20字节(相当于5个int);最后循环打印 arr2 内容。
运行结果:
1.3memcpy的模拟实现
#include <assert.h>
void * my_memcpy(void * dst, const void * src, size_t count)
{
void * ret = dst;
assert(dst != NULL);
assert(src != NULL);
while (count--)
{
*(char *)dst = *(char *)src;
dst = (char *)dst + 1;
src = (char *)src + 1;
}
return ret;
}
🧐分析:用 assert 断言保证指针非空;再强转为 char* 实现逐字节拷贝,保证通用性;接着循环 count 次,完成指定字节数拷贝;最后返回复制后目标空间地址。
二.memmove -----> 内存块拷贝(⬅️可处理重叠)
2.1函数原型(包含功能,参数,返回值)
函数原型:
void * memmove ( void * destination, const void * source, size_t num );
功能:
- 功能与
memcpy一致,但可以安全处理内存重叠。- 无论源、目标内存是否重叠,都能正确复制。
- 头文件:
<string.h>
参数:
destination:目标内存起始地址source:源内存起始地址num:要复制的字节数
返回值:
返回目标内存
destination的起始地址。
2.2举例
#include <stdio.h>
#include <string.h>
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
memmove(arr1 + 2, arr1, 20);
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr1[i]);
}
return 0;
}
🧐分析:先在同一个数组内进行拷贝,存在内存重叠;再使用 memmove 保证数据不被破坏;最后打印数组,观察重叠拷贝结果。
运行结果:

2.3memmove的模拟实现
#include <assert.h>
void * my_memmove(void * dst, const void * src, size_t count)
{
void * ret = dst;//保存目标地址
assert(dst != NULL);
assert(src != NULL);
//情况1:不重叠,从前往后拷贝
if (dst <= src || (char *)dst >= (char *)src + count)
{
while (count--)
{
*(char *)dst = *(char *)src;
dst = (char *)dst + 1;
src = (char *)src + 1;
}
}
//情况2:重叠,从后往前拷贝
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 -----> 内存块按字节设置
3.1函数原型(包含功能,参数,返回值)
函数原型:
void * memset ( void * ptr, int value, size_t num );
功能:
- 将
ptr指向的内存,按字节设置 为value。- 共设置
num个字节。- 头文件:
<string.h>
参数:
ptr:要设置的内存起始地址value:要设置的值(只取低 8 位,按字节设置)num:要设置的字节数
返回值:
返回
ptr指向的内存起始地址
3.2举例
#include <stdio.h>
#include <string.h>
int main()
{
char str[] = "hello world";
memset(str, 'x', 6);
printf("%s\n", str);
return 0;
}
🧐分析:先对字符串前 6 字节批量赋值为 ‘x’;然后按字节修改,速度快,适合初始化。
运行结果:

四.memcmp -----> 内存块逐字节比较
4.1函数原型(包含功能,参数,返回值)
函数原型:
int memcmp ( const void * ptr1, const void * ptr2, size_t num );
功能:
- 比较
ptr1和ptr2指向的内存块,逐字节比较前num个字节- 不关心数据类型,只比较二进制值。
- 头文件:
<string.h>
参数:
ptr1:待比较内存块 1ptr2:待比较内存块 2num:要比较的字节数
返回值:
- 当
>0时:ptr1 > ptr2- 当
=0时:ptr1 == ptr2- 当
<0时:ptr1 < ptr2
4.2举例
#include <stdio.h>
#include <string.h>
int main()
{
char buffer1[] = "DWgaOtP12df0";
char buffer2[] = "DWGAOTP12DF0";
int n = memcmp(buffer1, buffer2, sizeof(buffer1));
if (n > 0)
printf("'%s' 大于 '%s'\n", buffer1, buffer2);
else if (n < 0)
printf("'%s' 小于 '%s'\n", buffer1, buffer2);
else
printf("'%s' 与 '%s' 相同\n", buffer1, buffer2);
return 0;
}
🧐分析:先逐字节比较两块内存区域;然后根据返回值判断大小关系。
运行结果:

🎯总结
1. memcpy:通用内存拷贝,以字节为单位复制数据,不支持内存重叠,但效率较高。
2. memmove:pro版本内存拷贝,支持内存重叠,工程中更安全。
3. memset:以字节为单位初始化内存,常用于内存置 0、置字符。
4. memcmp:以字节为单位比较两块内存,不受 \0 结束符限制,可比较任意数据。
5. 四个函数均依赖头文件<string.h>,以 void* 为参数,支持任意数据类型操作
⚠️易错点
memcpy处理重叠内存,导致数据被覆盖、结果异常。memset按字节赋值,误用给int数组设为1,结果并非每个元素为1。- 拷贝
/比较时,字节数num计算错误,造成内存越界。- 模拟实现时,未将
void*强转为char*,无法正确逐字节操作。- 忘记使用
assert(断言)校验指针合法性,传入空指针导致程序崩溃。- 混淆
memcmp与strcmp:memcmp不遇到\0停止,会严格比较num个字节。- 遗漏头文件
<string.h>,导致函数未定义报错。
👀 关注 一路同行,从入门到大师,慢慢沉淀、稳步成长
❤️ 点赞 鼓励原创,让优质内容被更多人看见
⭐ 收藏 收好核心知识点与实战技巧,需要时随时查阅
💬 评论 分享你的疑问或踩坑经历,一起交流避坑、共同进步
更多推荐

所有评论(0)