C语言内存函数

在 C 语言的编程世界里,内存管理至关重要,而内存函数则是开发者操控内存的得力工具。今天,我们就一同深入探索 C 语言中几个常用内存函数的奥秘,包括memcpymemmovememsetmemcmp

1.memcpy:内存数据复制大师

memcpy函数用于从源内存地址source开始,向后复制指定字节数num的数据到目标内存地址destination。其函数原型为:void *memcpy(void *destination, const void *source, size_t num);。需要注意的是,memcpy在复制过程中遇到'\0'不会停止,而且当源和目标内存有重叠时,复制结果是未定义的。

来看一个简单示例:

cpp 复制代码
#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的前 20 个字节(也就是前 5 个int型元素)复制到arr2中。

下面是memcpy的模拟实现:

cpp 复制代码
void *memcpy(void *dst, const void *src, size_t count) {
    void *ret = dst;
    // 断言确保目标和源指针有效
    assert(dst);
    assert(src);

    while (count--) {
        // 逐字节复制
        *(char *)dst = *(char *)src;
        dst = (char *)dst + 1;
        src = (char *)src + 1;
    }
    return ret;
}

在这个模拟实现中,通过assert检查指针有效性,然后利用while循环逐字节复制数据,保证内存数据的准确传输。

2.memmove:处理重叠内存的高手

memmove函数的功能与memcpy相似,原型为void *memmove(void *destination, const void *source, size_t num);,但它的优势在于能够处理源内存块和目标内存块重叠的情况。

比如下面这个例子:

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

这段代码将arr1的前 20 个字节复制到从arr1 + 2开始的位置,由于存在内存重叠,memmove能够正确处理。

memmove的模拟实现稍微复杂一些:

cpp 复制代码
void *memmove(void *dst, const void *src, size_t count) {
    void *ret = dst;
    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;
}

这里通过判断目标和源地址的关系,分别处理非重叠和重叠两种情况,确保在各种场景下都能准确复制数据。

3.memset:内存数据设置专家

memset函数用于将内存区域ptr的前num个字节设置为指定值value,函数原型为void *memset(void *ptr, int value, size_t num);

例如:

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

int main() {
    char str[] = "hello world";
    memset(str, 'x', 6);
    printf(str);
    return 0;
}

运行这段代码,会将str的前 6 个字符替换为'x',输出xxxxxxworldmemset在初始化内存、清空缓冲区等场景中经常使用。

4.memcmp:内存数据比较利器

memcmp函数用于比较从ptr1ptr2指针指向的位置开始的num个字节,函数原型为int memcmp(const void *ptr1, const void *ptr2, size_t num);。它的返回值用于指示两个内存块内容的关系:

  • 返回值小于 0,表示ptr1中第一个不匹配的字节小于ptr2中的对应字节(按无符号字符值比较);
  • 返回值等于 0,表示两个内存块内容相等;
  • 返回值大于 0,表示ptr1中第一个不匹配的字节大于ptr2中的对应字节(按无符号字符值比较)。

示例代码如下:

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

int main() {
    char buffer1[] = "DWgaOtP12df0";
    char buffer2[] = "DWGAOTP12DF0";
    int n;
    n = memcmp(buffer1, buffer2, sizeof(buffer1));

    if (n > 0)
        printf("'%s' is greater than '%s'.\n", buffer1, buffer2);
    else if (n < 0)
        printf("'%s' is less than '%s'.\n", buffer1, buffer2);
    else
        printf("'%s' is the same as '%s'.\n", buffer1, buffer2);

    return 0;
}

这段代码比较buffer1buffer2的内容,并根据比较结果输出相应信息。

通过对memcpymemmovememsetmemcmp这几个内存函数的学习,我们掌握了在 C 语言中高效处理内存数据的方法。它们在数据处理、内存初始化、数据比较等诸多场景中发挥着重要作用,是 C 语言开发者不可或缺的编程工具。希望大家在今后的编程实践中,能够灵活运用这些函数,编写出更加健壮、高效的代码。

相关推荐
消失的旧时光-19435 分钟前
用 C 实现一个简化版 MessageQueue
c语言·开发语言
Yue丶越1 小时前
【C语言】动态内存管理
c语言·开发语言
南棱笑笑生2 小时前
20251215给飞凌OK3588-C开发板适配Rockchip原厂的Buildroot【linux-6.1】系统时统计eth1的插拔次数
linux·c语言·开发语言·rockchip
刃神太酷啦2 小时前
Linux 进程核心原理精讲:从体系结构到实战操作(含 fork / 状态 / 优先级)----《Hello Linux!》(6)
java·linux·运维·c语言·c++·算法·leetcode
永恒-龙啸2 小时前
spooling假脱机输入输出模拟
c语言·开源·github
前端世界2 小时前
从“看不懂”到“能用”:一次搞清 C 语言指针数组
c语言·开发语言
发疯幼稚鬼2 小时前
归并排序与快速排序
c语言·数据结构·算法·排序算法
福尔摩斯张2 小时前
TCP协议深度解析:从报文格式到连接管理(超详细)
linux·c语言·网络·c++·笔记·网络协议·tcp/ip
光子物联单片机2 小时前
STM32单片机开发入门(十一)STM32CubeIDE下载安装及开发调试说明
c语言·stm32·单片机·嵌入式硬件·mcu
_codemonster3 小时前
自然语言处理容易混淆知识点(一)c-TF-IDF和TF-IDF的区别
c语言·自然语言处理·tf-idf