C语言内存函数详解:从基础到实战

在 C 语言的编程世界里,内存操作是家常便饭,为了方便高效地操作内存,C 标准库提供了好几个实用的内存函数。今天,我就来给大家详细介绍这些内存函数,从最常见的`memcpy`、`memmove`、`memset`,到`memcmp`,不仅讲怎么用,还带你亲手模拟实现它们,新手友好,保证让你学完就能上手!

 

 

memcpy:内存块复制的“搬运工”

 

 

  1. 函数原型

 

• `void *memcpy(void *dest, const void *src, size_t n);`

 

• 参数 dest 是目标内存块的指针,src 是源内存块的指针,n 是要复制的字节数。

 

• 返回值是 dest。

 

 

  2. 功能

 

• `memcpy`就像是内存里的“搬运工”,从源内存块(src)开始向后复制 n 个字节的内容到目标内存块(dest)中,不关心内存里存的是啥数据类型(字符、整数等),只管按字节搬。

 

 

  3. 注意事项

 

• 如果源内存块和目标内存块有重叠区域,`memcpy`的行为是未定义的(可能出错)。比如,从内存的第 100 字节开始复制到第 50 字节,且复制长度超过 50 字节,`memcpy`就可能把还没复制的数据给覆盖了。这种情况下,应该用`memmove`。

 

• 使用`memcpy`时,要确保源和目标内存块都是有效的,并且有足够的空间来容纳操作。

 

 

  4. 使用示例

 

#include <stdio.h>

#include <string.h>

 

int main() {

    char src[] = "hello world";

    char dest[20];

    memcpy(dest, src, sizeof(src)); // 复制整个 src 字符串

    dest[sizeof(src) - 1] = '\0'; // 添加字符串结束符

    printf("复制后的字符串:%s\n", dest);

    return 0;

}

 

  5. 模拟实现

 

• 思路:逐字节复制,从源内存块复制到目标内存块,复制 n 个字节。

 

#include <stdio.h>

 

void *my_memcpy(void *dest, const void *src, size_t n) {

    char *d = (char *)dest;

    const char *s = (const char *)src;

    for (size_t i = 0; i < n; i++) {

        d[i] = s[i];

    }

    return dest;

}

 

int main() {

    char src[] = "hello world";

    char dest[20];

    my_memcpy(dest, src, sizeof(src));

    dest[sizeof(src) - 1] = '\0';

    printf("复制后的字符串:%s\n", dest);

    return 0;

}

 

 

memmove:内存块复制的“快递员”(不怕重叠)

 

 

  1. 函数原型

 

• `void *memmove(void *dest, const void *src, size_t n);`

 

• 参数和返回值与`memcpy`一样。

 

 

  2. 功能

 

• `memmove`也是复制内存块的,但它比`memcpy`高级一点,能处理源和目标内存块有重叠的情况。它就像是“快递员”,不管源和目标是不是挨着,都能安全地把数据“快递”到目标地址。

 

 

  3. 使用场景

 

• 当源和目标内存块有重叠时,比如在字符串中把后面的部分复制到前面,或者前面复制到后面,就用`memmove`。

 

 

  4. 使用示例

 

#include <stdio.h>

#include <string.h>

 

int main() {

    char str[] = "hello world";

    memmove(str, str + 6, 5); // 把 "world" 复制到字符串开头

    str[5] = '\0'; // 添加字符串结束符

    printf("复制后的字符串:%s\n", str);

    return 0;

}

 

  5. 模拟实现

 

• 思路:先判断源和目标内存块的相对位置。如果源在目标后面,就从前往后复制;如果源在目标前面,就从后往前复制,避免数据被覆盖。

 

#include <stdio.h>

 

void *my_memmove(void *dest, const void *src, size_t n) {

    char *d = (char *)dest;

    const char *s = (const char *)src;

    if (d < s) { // 源在目标后面,从前往后复制

        for (size_t i = 0; i < n; i++) {

            d[i] = s[i];

        }

    } else { // 源在目标前面或相同位置,从后往前复制

        for (size_t i = n; i > 0; i--) {

            d[i - 1] = s[i - 1];

        }

    }

    return dest;

}

 

int main() {

    char str[] = "hello world";

    my_memmove(str, str + 6, 5);

    str[5] = '\0';

    printf("复制后的字符串:%s\n", str);

    return 0;

}

 

 

memset:内存块设置的“涂色器”

 

 

  1. 函数原型

 

• `void *memset(void *str, int c, size_t n);`

 

• 参数 str 是内存块的指针,c 是要设置的值(会被转换为 unsigned char),n 是要设置的字节数。

 

• 返回值是 str。

 

 

  2. 功能

 

• `memset`就像是给内存块“涂色”,把内存块的前 n 个字节都设置成指定的值 c。常用来初始化内存,比如把内存全设置为 0。

 

 

  3. 使用示例

 

#include <stdio.h>

#include <string.h>

 

int main() {

    char str[20];

    memset(str, 'A', 10); // 把 str 的前 10 个字节设置为 'A'

    str[10] = '\0'; // 添加字符串结束符

    printf("设置后的字符串:%s\n", str);

    return 0;

}

 

 

  4. 模拟实现

 

• 思路:逐字节设置,把内存块的前 n 个字节都设置为 c 的值(转换为 unsigned char)。

 

#include <stdio.h>

 

void *my_memset(void *str, int c, size_t n) {

    unsigned char *s = (unsigned char *)str;

    unsigned char value = (unsigned char)c;

    for (size_t i = 0; i < n; i++) {

        s[i] = value;

    }

    return str;

}

 

int main() {

    char str[20];

    my_memset(str, 'A', 10);

    str[10] = '\0';

    printf("设置后的字符串:%s\n", str);

    return 0;

}

 

 

memcmp:内存块比较的“裁判员”

 

 

  1. 函数原型

 

• `int memcmp(const void *str1, const void *str2, size_t n);`

 

• 参数 str1 和 str2 是两个内存块的指针,n 是要比较的字节数。

 

• 返回值:

 

• 如果两个内存块的前 n 个字节相等,返回 0。

 

• 如果 str1 小于 str2,返回负数。

 

• 如果 str1 大于 str2,返回正数。

 

 

  2. 功能

 

• `memcmp`就像是在比武场上当“裁判员”,逐字节比较两个内存块的前 n 个字节,判断它们的大小关系。

 

 

  3. 使用示例

 

#include <stdio.h>

#include <string.h>

 

int main() {

    char str1[] = "hello";

    char str2[] = "hella";

    int result = memcmp(str1, str2, 5);

    if (result == 0) {

        printf("两个内存块的前 5 个字节相等\n");

    } else if (result < 0) {

        printf("str1 的前 5 个字节小于 str2\n");

    } else {

        printf("str1 的前 5 个字节大于 str2\n");

    }

    return 0;

}

 

 

  4. 模拟实现

 

• 思路:逐字节比较,如果找到不同的字节就返回它们的差值,比较完 n 个字节都相同就返回 0。

 

#include <stdio.h>

 

int my_memcmp(const void *str1, const void *str2, size_t n) {

    const unsigned char *s1 = (const unsigned char *)str1;

    const unsigned char *s2 = (const unsigned char *)str2;

    for (size_t i = 0; i < n; i++) {

        if (s1[i] != s2[i]) {

            return s1[i] - s2[i];

        }

    }

    return 0;

}

 

int main() {

    char str1[] = "hello";

    char str2[] = "hella";

    int result = my_memcmp(str1, str2, 5);

    if (result == 0) {

        printf("两个内存块的前 5 个字节相等\n");

    } else if (result < 0) {

        printf("str1 的前 5 个字节小于 str2\n");

    } else {

        printf("str1 的前 5 个字节大于 str2\n");

    }

    return 0;

}

 

 

总结

 

今天,咱们把 C 语言里超实用的内存函数`memcpy`、`memmove`、`memset`和`memcmp`一网打尽啦!从`memcpy`的内存块复制,到`memmove`的重叠区域复制,再到`memset`的内存初始化,以及`memcmp`的内存比较,新手友好,这些函数在日常编程里超常用,学会它们,内存操作不再是难题!希望大家能多练练,把每个函数都玩得明明白白。

 

宝子们,今天的内容是不是让你对 C 语言的内存函数有了全新的认识?有没有哪个函数的模拟实现让你眼前一亮,或者曾经困扰你的地方现在豁然开朗?快来评论区分享你的学习心得或者疑问吧!说不定你的分享就能帮到其他小伙伴,大家一起进步,下次咱们继续在 C 语言的编程之旅中探索更多宝藏知识!​

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值