C语言内存函数完全指南:memcpy/memmove/memset/memcmp

C语言内存函数完全指南:memcpy/memmove/memset/memcmp

除了字符串操作,C标准库还提供了一系列直接操作内存块的函数。这些函数以字节为单位处理数据,能够高效地拷贝、移动、设置和比较任意类型的内存块。本文将详细讲解 memcpymemmovememsetmemcmp 的用法、区别及模拟实现,帮助读者安全灵活地操纵内存。

目录


一、memcpy的使用和模拟实现

void *memcpy(void *destination, const void *source, size_t num);

  • source 位置向后复制 num 个字节到 destination
  • 不会因为遇到 '\0' 而停止,完全按字节数操作。
  • 如果源和目标内存区域重叠 ,行为未定义(应使用 memmove)。

示例:拷贝整型数组的前5个元素(20字节)

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

模拟实现

c 复制代码
void *my_memcpy(void *dst, const void *src, size_t count) {
    void *ret = dst;
    assert(dst && src);
    while (count--) {
        *(char*)dst = *(char*)src;
        dst = (char*)dst + 1;
        src = (char*)src + 1;
    }
    return ret;
}

关键 :使用 char* 指针逐字节拷贝,保证通用性。


二、memmove的使用和模拟实现

void *memmove(void *destination, const void *source, size_t num);

  • 功能与 memcpy 类似,但允许源和目标内存重叠
  • 当无法确定是否重叠时,应优先使用 memmove

示例:将数组前5个元素移动到从下标2开始的位置

c 复制代码
int arr[] = {1,2,3,4,5,6,7,8,9,10};
memmove(arr+2, arr, 20);  // 重叠拷贝
// 结果:1 2 1 2 3 4 5 8 9 10

模拟实现(需考虑拷贝方向):

  • 若目标地址在源地址之前,从前往后拷贝。
  • 若目标地址在源地址之后且重叠,从后往前拷贝。
c 复制代码
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函数的使用

void *memset(void *ptr, int value, size_t num);

  • ptr 指向的内存块的前 num 个字节每个字节 设置为 valuevalue 转为 unsigned char 后填充)。
  • 常用于数组或结构体的快速初始化。

示例 :将字符串前6个字符改为 'x'

c 复制代码
char str[] = "hello world";
memset(str, 'x', 6);
printf("%s\n", str);  // "xxxxx world"

注意memset 以字节为单位,不能用于将整型数组全部设为 1(因为会变成 0x01010101),除非值为 0

c 复制代码
int arr[10];
memset(arr, 0, sizeof(arr));   // 正确,全部置0
memset(arr, 1, sizeof(arr));   // 每个字节变1,整型值变为 0x01010101

四、memcmp函数的使用

int memcmp(const void *ptr1, const void *ptr2, size_t num);

  • 比较 ptr1ptr2 指向的内存块的前 num 个字节。
  • 返回值与 strcmp 类似:
    • <0:ptr1 的字节值小于 ptr2
    • 0:相等
    • >0:ptr1 的字节值大于 ptr2

示例:比较两个字符串(区分大小写)

c 复制代码
char buf1[] = "DWgaOtP12df0";
char buf2[] = "DWGAOTP12DF0";
int n = memcmp(buf1, buf2, sizeof(buf1));
if (n > 0)
    printf("%s is greater than %s\n", buf1, buf2);
else if (n < 0)
    printf("%s is less than %s\n", buf1, buf2);
else
    printf("equal\n");

注意memcmp 比较的是原始字节值(按 unsigned char 比较),而不是字符串语义,不会因为 '\0' 提前停止。


总结:内存函数以字节为单位操作内存,适用于任何数据类型。memcpy 高效但不能重叠拷贝;memmove 支持重叠,更安全;memset 快速填充字节;memcmp 比较内存块。掌握这些函数并理解其模拟实现,能够有效处理数组、结构体等内存块,提升代码性能和可靠性。特别注意 memset 的字节填充特性及 memmove 的方向处理。

相关推荐
2201_761199041 小时前
python运维1
运维·开发语言·python
Cx330❀2 小时前
【Qt 核心机制篇】深度解析 Qt 信号与槽(Signals & Slots)机制:从底层原理、实战演练到 Lambda 进阶
linux·开发语言·c++·人工智能·qt·ubuntu
z落落2 小时前
C# ArrayList 动态集合(接口/区别/API/深浅拷贝)+ List<T> 泛型集合
开发语言·c#
Cx330❀2 小时前
【Linux网络】从零构建高性能UDP服务器:从Echo到英译汉业务级实现
大数据·linux·服务器·开发语言·网络·c++·udp
basketball6162 小时前
Golang:基础语法总结
开发语言·后端·golang
兰令水2 小时前
leecodecode【双指针题2】【2026.5.26打卡-java版本】
java·开发语言·算法
不吃土豆的马铃薯2 小时前
TCP 三次握手 / 四次挥手详解
服务器·开发语言·网络·c++·网络协议·tcp/ip
金刚狼882 小时前
用atomic解决全局变量跨线程修改的问题
c语言