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 语言开发者不可或缺的编程工具。希望大家在今后的编程实践中,能够灵活运用这些函数,编写出更加健壮、高效的代码。

相关推荐
小_楠_天_问1 小时前
第二课:ESP32 使用 PWM 渐变控制——实现模拟呼吸灯或音调变化
c语言·嵌入式硬件·mcu·esp32·arduino·pwm·esp32-s3
秋山落叶万岭花开ღ1 小时前
C语言顺序表应用详解:从理论到实践
c语言
2301_803554521 小时前
c++和c的不同
java·c语言·c++
小狗祈祷诗2 小时前
day20-线性表(链表II)
c语言·数据结构·链表
白露秋483 小时前
C——五子棋小游戏
c语言·游戏
whoarethenext7 小时前
c/c++爬虫总结
c语言·c++·爬虫
在右ZR7 小时前
嵌入式(c语言篇)Day9
c语言
水水沝淼㵘9 小时前
嵌入式开发学习日志(数据结构--单链表)Day20
c语言·开发语言·数据结构·学习·算法
人类恶.11 小时前
C 语言学习笔记(6)
c语言·笔记·学习