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 的方向处理。

相关推荐
cypking41 分钟前
Objective-C 语法完整学习手册(小白自学 + 开发备查)
c语言·开发语言·学习·objective-c
ambition202422 小时前
操作系统同步:读者-写者问题与读写公平法详解(附每个 PV 操作含义)
linux·开发语言·数据结构·unix
chuan.bai5 小时前
Java RAG 实战(第 11 篇):RAG 知识工作台网页
java·开发语言·人工智能
离陌在学C#7 小时前
C# 事件(Event)详解:从概念到实战
开发语言·c#
Terra.K8 小时前
Java异常学习[特殊字符]
java·开发语言·学习
葡萄城技术团队9 小时前
InfluxDB 2\.x 深度解析:核心架构、Flux 函数与制造业落地指南(三)
java·开发语言·架构
counting money9 小时前
Java IO流详解:从InputStream到文件操作实战
java·开发语言·python
wuyk55510 小时前
98.C语言易混难点:字符数组与字符串指针的底层差异
c语言·开发语言·c++·stm32·嵌入式硬件·算法
峥无10 小时前
从0到1手撕红黑树:封装实现 my_map 与 my_set(SGI-STL 源码级深度解析)
开发语言·c++·笔记·算法·stl
波特率11520010 小时前
C++新特性---属性说明符与标准属性
开发语言·c++