• C语言内存函数


    前言

    上篇博客我们分析了字符函数和字符串函数,这篇咱们就来看看内存函数

    个人主页小张同学zkf

    若有问题,评论区见

    感兴趣就关注一下吧

     


    目录

     1. memcpy使用和模拟实现

     2. memmove使用和模拟实现

     3. memset函数的使用

    4. memcmp函数的使用


     1. memcpy使用和模拟实现

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

     这个函数有点类似于上篇博客的strncpy,但是strncpy只能拷贝字符串的,而咱们现在遇到的函数是memcpy,这个没有具体拷贝什么,它的功能就是将一个内存块里的数据拷贝到另一个内存块

    注意:

    • 函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存位置。
    • 这个函数在遇到 '\0' 的时候并不会停下来。
    •若这俩内存块有重叠,那复制的结果都是未定义的

    我们可以看一个例子

    #include
    #include
    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;
    }

    这里需要强调一下,一个int类型是4个字节,那拷贝20个字节相当于将5个整形拷贝过去!!!

    所以这个结果就是 把1,2,3,4,5前五个整形拷贝过来

    我们来看看memcpy模拟实现

    我们首先要知道第二个参数指针指向的对象不能改变,它是要拷贝的东西,其次这个函数是什么类型都能接受的,所以参数类型用void*来接受,那返回目的地的指针也是void*,然后这个函数是一个字节一个字节的拷贝,所以我们要强制转换成char*类型,因为char*解引用访问的空间就是一个字节

    void * memcpy ( void * dst, const void * src, size_t count)
    {
    void * ret = dst;
    assert(dst);
    assert(src);
    /*
    * copy from lower addresses to higher addresses
    */
    while (count--) {
    *(char *)dst = *(char *)src;
    dst = (char *)dst + 1;
    src = (char *)src + 1;
    }
    return(ret);
    }

     2. memmove使用和模拟实现

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

    这个函数其实只跟memcpy有一个差别,这个函数源内存块和目标内存块是可以重叠的,而memcpy不能重叠

    注意:

    • 和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
    • 如果源空间和目标空间出现重叠,就得使⽤memmove函数处理。

    我们来看一下这个函数的模拟实现

    这个函数我们分析一下,拷贝的时候要注意不要覆盖源内存块的内容,我么画图来看一下

    这个就是覆盖上了导致不是我们想要的拷贝,这是从前向后拷贝的,从3开始向后拷贝的,那我们换个方向拷贝,从后向前拷贝试试呢

    这个就没有覆盖,这个就是从后向前,就是这个是从5开始向前拷贝的,但我们再想想真的所有情况都适合于 从后向前拷贝的吗,从后想前拷贝就不会出现覆盖吗

    我们来看一下这种情况

     

    这种情况从后向前拷贝也就是从5开始向前拷贝就被覆盖了,返而这种情况从前向后拷贝不被覆盖 

    那我们是不是就应该总结一下,什么时候从前向后拷贝不用担心覆盖,什么时候从后向前拷贝不用担心覆盖 

    我们对比一下这几张图发现,目标空间首指针小于源空间的首指针时应从前向后拷贝才正常,而目标空间首指针大于源空间的首指针时,应从后向前拷贝才正常

    所以if条件有了,在从后向前拷贝时记得将地址加到拷贝的最后一位

    以下是代码

    void * memmove ( void * dst, const void * src, size_t count)
    {
    void * ret = dst;
    if (dst <= src || (char *)dst >= ((char *)src + count)) {
    /*
    * Non-Overlapping Buffers
    * copy from lower addresses to higher addresses
    */
    while (count--) {
    *(char *)dst = *(char *)src;
    dst = (char *)dst + 1;
    src = (char *)src + 1;
    }
    }
    else {
    /*
    * Overlapping Buffers
    * copy from higher addresses to lower addresses
    */
    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函数的使用

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

    这个函数就是将第一个参数的内存块设置成num个字节的第二个参数这个整形值

    我们来看一下这个函数是如何使用的

    1. #include
    2. #include
    3. int main ()
    4. {
    5. char str[] = "hello world";
    6. memset (str,'x',6);
    7. printf(str);
    8. return 0;
    9. }

     结果

    xxxxxxworld

    4. memcmp函数的使用

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

    比较内存块里数据的大小,记住是一个一个字节比较的!!!
    注意:

    • 比较从ptr1和ptr2指针指向的位置开始,向后的num个字节
    • 返回值如下:

    我们来看看这个函数的使用

    1. #include <stdio.h>
    2. #include <string.h>
    3. int main()
    4. {
    5. char buffer1[] = "DWgaOtP12df0";
    6. char buffer2[] = "DWGAOTP12DF0";
    7. int n;
    8. n = memcmp(buffer1, buffer2, sizeof(buffer1));
    9. if (n > 0)
    10. printf("'%s' is greater than '%s'.\n", buffer1, buffer2);
    11. else if (n < 0)
    12. printf("'%s' is less than '%s'.\n", buffer1, buffer2);
    13. else
    14. printf("'%s' is the same as '%s'.\n", buffer1, buffer2);
    15. return 0;
    16. }

     

     


    结束语

    这篇博客内存函数要和上一篇博客字符串函数区分清楚,可以对比区分一下

    OK感谢观看


     

  • 相关阅读:
    065:mapboxGL在一个图层中随机添加100个标记(marker)
    PDF怎么合并?这些合并方法你该知道
    dva搭建项目实例
    Redis源码篇(7)——哨兵模式
    算法刷题第一天:二分查找
    【从零开始学习 SystemVerilog】2.10、SystemVerilog 数据类型—— Associative Array(关联数组)
    预训练相关知识
    Windows OpenGL ES 图像绿幕抠图
    Spark lazy list files 的实现
    Proxifier联动BurpSuite抓取小程序
  • 原文地址:https://blog.csdn.net/m0_74091744/article/details/136718586