C语言核心内存操作:memcpy、memmove、memset与memcmp深度解析
C语言提供了强大的内存操作能力,其中 memcpy、memmove、memset 和 memcmp 是最常用的四个函数。理解它们的区别、底层实现原理及边界情况(如内存重叠),是编写高性能C程序的基础。
memcpy:基础内存拷贝
memcpy 用于从源地址 source 向目标地址 destination 复制 num 个字节的数据。其核心特性包括:
- 无类型限制:基于
void*指针操作,可拷贝任意数据类型(结构体、数组等)。 - 不识别终止符:即使遇到字符串结束符
'\0'也不会停止,严格按字节数复制。 - 未定义行为:如果源和目标内存区域发生重叠,结果是不确定的。
第1步:理解 memcpy 的通用性
由于使用 void* 作为参数类型,memcpy 打破了字符串拷贝的限制。在实际操作中,通常将其强转为 char* 以进行逐字节操作。
/* num是几个字节的意思 */
void* my_memcpy(void* dest, const void* src, size_t num)
{
assert(dest && src);
void* ret = dest;
while (num--)
{
// 和void*连用char*,分成最小然后一个一个传
*(char*)dest = *(char*)src;
((char*)dest)++; // void*无类型不好直接加加,就强转char*再加加
((char*)src)++;
}
return ret;
}
第2步:处理内存重叠问题
当源地址与目标地址存在交集时,简单的正向拷贝会导致数据被覆盖从而产生错误。
为解决此问题,C语言标准引入了 memmove。但在部分编译器(如Visual Studio)的实现中,memcpy 可能内部已优化为支持重叠拷贝,效果等同于 memmove。然而,为了保证代码的跨平台标准和严谨性,建议明确区分二者用途。
第3步:注意内存边界
若目标缓冲区空间不足,强行拷贝将导致程序崩溃或数据越界。
memmove:安全处理重叠拷贝
memmove 专门设计用于处理内存重叠场景。C语言规范明确指出:memcpy 仅保证非重叠拷贝,而 memmove 保证在所有情况下(含重叠)均能正确执行。
第4步:分析拷贝方向策略
解决重叠问题的关键在于确定拷贝方向:
- 正向拷贝(dest < src):当目标地址在源地址之前时,可以从前往后拷贝,先处理低地址部分,不会影响尚未读取的高地址数据。
- 反向拷贝(dest > src):当目标地址在源地址之后时,必须从后往前拷贝。先保存并写入高地址数据,防止前面的数据被新值覆盖。
第5步:memmove 源码实现
通过判断地址关系选择拷贝方向,确保数据的完整性。
/* num是几个字节的意思 */
void* my_memmove(void* dest, const void* src, size_t num)
{
assert(dest && src);
void* ret = dest;
if (dest < src)
{
// 源内存从前向后拷贝
while (num--)
{
*(char*)dest = *(char*)src;
((char*)dest)++;
((char*)src)++;
}
}
else
{
// 源内存从后向前拷贝
while (num--)
{
*((char*)dest+num) = *((char*)src+num);
}
}
return ret;
}
memset:内存初始化与设置
memset 用于将指定内存区域 dest 的前 num 个字节设置为指定的字符 value。常用于结构体清零或初始化数组。
memcmp:内存块比较
与 strcmp 类似,但操作对象是内存块而非字符串。memcmp 比较两个内存区域 buf1 和 buf2 的前 count 个字节。
分析:基本逻辑与字符串比较一致,即逐字节比对直到找到差异或达到指定长度。需注意 count 参数不要超出实际内存范围,因为内存操作没有自动补 '\0' 的机制。
第6步:memcmp 源码实现
// buf1内容比buf2大则返回 >0, 反之 <0
int my_memcmp(const void* buf1, const void* buf2, size_t count)
{
assert(buf1 && buf2);
while (--count && *(char*)buf1 == *(char*)buf2)
{
((char*)buf1)++;
((char*)buf2)++;
}
if (*(char*)buf1 - *(char*)buf2 > 0)
return 1;
if (*(char*)buf1 - *(char*)buf2 < 0)
return -1;
return 0;
}
总结
掌握 memcpy 的高效性与 memmove 的安全性是C语言编程的关键。在处理内存重叠时必须使用 memmove;在进行大规模数据初始化时使用 memset;而在二进制数据对比时选用 memcmp。合理运用这些底层函数,能有效提升程序的健壮性与执行效率。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









