深入理解 C 语言内存操作函数:memcpy、memmove、memset、memcmp

文章目录


前言

在 C 语言编程中,内存操作 是核心技能之一。不同于字符串函数仅针对字符处理,内存函数可以操作任意类型数据,以字节为单位读写内存,是实现高效数据拷贝、初始化、比较的关键工具。

本文将系统讲解 C 语言四大内存函数:memcpy、memmove、memset、memcmp,包含函数用法、核心特性、代码示例与模拟实现,帮你彻底掌握内存操作逻辑。


一、memcpy ------ 基础内存拷贝

1.函数原型

c 复制代码
void *memcpy(void *destination, const void *source, size_t num);

2.核心特性

  1. 从 source 起始位置,拷贝 num 字节数据到 destination 内存地址
  2. 遇到 \0 不会停止,不受字符串结束符限制
  3. 不支持内存重叠,重叠拷贝结果未定义
  4. 适用于任意数据类型(int、float、结构体等)

3.使用示例

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};
    // 拷贝 20 字节 = 5 个 int 类型数据
    memcpy(arr2, arr1, 20);
    
    for (int i = 0; i < 10; i++)
    {
        printf("%d ", arr2[i]);
    }
    return 0;
}

输出结果:1 2 3 4 5 0 0 0 0 0

4.模拟实现

c 复制代码
#include <assert.h>
void * my_memcpy ( void * dst, const void * src, size_t count)
{
    void * ret = dst;
    // 断言保证指针有效
    assert(dst && src);
    
    while (count--) {
        // 强转为char*,逐字节拷贝
        *(char *)dst = *(char *)src;
        dst = (char *)dst + 1;
        src = (char *)src + 1;
    }
    return ret;
}

二、memmove ------ 支持重叠的安全内存拷贝

1.函数原型

c 复制代码
void *memmove(void *destination, const void *source, size_t num);

2.核心特性

  1. 功能与 memcpy 一致,唯一区别:支持内存重叠
  2. 内存重叠场景下,必须使用 memmove 保证结果正确
  3. 拷贝逻辑:

3.使用示例

c 复制代码
#include <stdio.h>
#include <string.h>

int main()
{
    int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
    // 内存重叠:arr1+2 与 arr1 地址重叠
    memmove(arr1+2, arr1, 20);
    
    for (int i = 0; i < 10; i++)
    {
        printf("%d ", arr1[i]);
    }
    return 0;
}

输出结果:1 2 1 2 3 4 5 8 9 10

4.模拟实现

c 复制代码
#include <assert.h>
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 ------ 内存批量初始化

1.函数原型

c 复制代码
void * memset ( void * ptr, int value, size_t num );

2.核心特性

  1. 以字节为单位填充内存,批量设置数据(与char很对应)
  2. 常用于数组、结构体的初始化(清零 / 置值)
  3. 注意:对 int 类型赋值非 0 值会出错(逐字节覆盖,且int类型存入内存的是补码)

3.使用示例

c 复制代码
#include <stdio.h>
#include <string.h>

int main ()
{
    char str[] = "hello world";
    // 前6个字节替换为'x'
    memset (str,'x',6);
    printf("%s\n", str);
    return 0;
}

输出结果:xxxxxxworld

四、memcmp ------ 内存字节级比较

1.函数原型

c 复制代码
int memcmp ( const void * ptr1, const void * ptr2, size_t num );

2.核心特性

  1. 比较ptr1和ptr2起始位置的num字节内存
  2. 逐字节比较,按无符号 char判断大小(1个字节大小)
  3. 返回值规则:
    返回小于0的值:ptr1 < ptr2
    返回0:ptr1 == ptr2
    返回大于0的值:ptr1 > ptr2

3.使用示例

#include <stdio.h>

#include <string.h>

c 复制代码
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;
}

五、四大内存函数总结对比

函数 功能 内存重叠 操作单位 核心场景
memcpy 内存拷贝 不支持 字节 无重叠数据拷贝
memmove 内存拷贝 支持 字节 重叠 / 无重叠通用
memset 内存初始化 - 字节 清零、批量置值
memcmp 内存比较 - 字节 任意类型数据比较

六、关键注意事项

  1. 内存函数均依赖<string.h>头文件
  2. 操作以字节为单位,与数据类型无关
  3. 重叠拷贝必须用memmove,避免未定义行为
  4. memset对 int 类型仅推荐用于清零

总结

掌握 C 语言内存函数,是进阶编程的必经之路。无论是底层开发、数据结构还是性能优化,灵活使用memcpy/memmove/memset/memcmp,能让你的代码更简洁、高效、安全。

以上就是该篇博客的内容了,如果内容存在不足,请大佬多多包涵并不吝赐教,会在写出优秀好文的路上努力拼搏达,感谢支持!!!

一键三连。[1](#1)感谢佬们的支持😄


  1. 点赞,关注,收藏qwq感谢佬佬们 ↩︎
相关推荐
广师大-Wzx3 小时前
一篇文章看懂MySQL数据库(下)
java·开发语言·数据结构·数据库·windows·python·mysql
野生技术架构师3 小时前
Java NIO到底是个什么东西?
java·开发语言·nio
lolo大魔王3 小时前
Go语言的异常处理
开发语言·后端·golang
chh5634 小时前
C++--模版初阶
c语言·开发语言·c++·学习·算法
灼灼桃花夭5 小时前
js之阳历 → 农历(含时辰)转换函数
开发语言·前端·javascript
派大星酷5 小时前
Java 调用 Kimi API 实战:实现与大模型的简单对话
java·开发语言·ai编程
小李子呢02115 小时前
前端八股性能优化(1)---防抖和节流
开发语言·前端·javascript
henrylin99995 小时前
Hermes Agent 核心运行系统调用流程--源码分析
开发语言·人工智能·python·机器学习·hermesagent
珎珎啊5 小时前
Python3 字符串核心知识点
开发语言·python