虫子 内存函数 众神起步,万语之基,软硬桥梁,帝国大厦

举报
虫子VV 发表于 2022/04/21 13:12:15 2022/04/21
【摘要】 内存函数memcpy内存拷贝函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。 这个函数在遇到 '\0' 的时候并不会停下来。如果source和destination有任何的重叠,复制的结果都是未定义的。原格式分析*字面上意思只要是内存里面的东西就都可以进行拷贝,所以就打破了字符串拷贝的魔咒,什么类型都可以进行拷贝,那就不需要想来,肯定回和...


内存函数

memcpy内存拷贝

  • 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。

  • 这个函数在遇到 '\0' 的时候并不会停下来。

  • 如果source和destination有任何的重叠,复制的结果都是未定义的。

原格式

image-20210912150415470

分析

*字面上意思只要是内存里面的东西就都可以进行拷贝,所以就打破了字符串拷贝的魔咒,什么类型都可以进行拷贝,那就不需要想来,肯定回和万能类型(通用类型指针-无类型指针)void^^有关,因为当时做qsort还是印象深刻的

 /*num是几个字节的意思*/
 void* my_memcpy(void* dest, const void* src, size_t num)
 {
     assert(dest && src);
     void* ret = dest;
     while (num--)
     {
         //和void*连用char*,分成最小然后一个一个传
         *(char*)dest = *(char*)src;
         ((char*)dest)++;//void*无类型不好直接加加,就强转char*再加加
         ((char*)src)++;
     }   
     return ret;
 }

内存拷贝的问题

1.内存相关连的话,就会拷贝错误

image-20210912174618496

那你怎么解决内存相关连还不会有上面的错误,正面赋值交集的内存空间会被操作两次,就会改变原来的值,那我们怎么做呢,如果从后面来呢,前面操作两次会把后面的变了,那就先把后面的拿走赋值,不就间接的改变了原来会变的情况了吗,所以这样上面的代码就得修改了,这是朝后面拷贝的情况,如果提目是朝前面拷贝的话,是不是从后面来就有问题了,反而从前面来会比较完美,所以我们得两种情况都得考虑到

所以为了解决重叠拷贝的问题就有了memmove这个函数

2.内存不够了还要朝里面拷贝直接程序挂了

image-20210912175703527

memmove内存重叠拷贝

用来处理内存重叠的情况

C语言规定

memcpy 只要处理内存不重叠的拷贝就可以

memmove 处理重叠内存拷贝

我们重写memcpy的代码是满足C语言要求的,在vs这个编译器中memcpy实际上是超额完成任务了,他的效果已经和memmove效果一样了

image-20210912201352859

你会发现他们跑出来的效果 是一样的,所以上面那个测试我就是用我自己的代码测试的(已经达到C语言的标准了)

我们再精细点就是memmove的内容了

原格式

image-20210912195704561

分析

image-20210912200345318

image-20210912210111460

image-20210912210718304

image-20210912212544483

 /*num是几个字节的意思*/
 void* my_memmove(void* dest,const void* src, size_t num)//memmove和memcpy的参数是一样的
 {
     assert(dest && src);
     void* ret = dest;
     if (dest < src)
     {
         while (num--)
         {
             //sre内存从前向后拷贝
             //和void*连用char*,分成最小然后一个一个传
             *(char*)dest = *(char*)src;
             ((char*)dest)++;//void*无类型不好直接加加,就强转char*再加加
             ((char*)src)++;
         }
     }
     else
     {
         while (num--)
         {
             //sre内存从后向前拷贝
             //和void*连用char*,分成最小然后一个一个传
             *((char*)dest+num) = *((char*)src+num);
             //((char*)dest)++;//void*无类型不好直接加加,就强转char*再加加
             //((char*)src)++;
         }
     }   
     return ret;
 }

image-20210912215713723

memset内存设置

将缓冲区设置为指定的字符。

原格式

image-20210912224129279

分析

image-20210913005714774

image-20210913012002615

 //变量c代表的是字符的ASCII码
 void* my_memset(void* dest, int c, size_t count)
 {   
     const unsigned char uc = c;    //把c转成字符,且不可变用const  
     void* ret = dest;
      int i = 0;
      for (i = 0; i < count; i++)
      {
         *(char*)dest = uc;
         ((char*)dest)++;
      }
      return ret;
 }


memcmp内存比较

和strcmp相似,只不过一个是比较字符串,一个比较内存,由于不知道什么类型,所以后面有字节个数限制,准确的说应该和strncmp相似,因为后面都有一个个数的参数

原格式

image-20210912222610487

分析

基本和字符串比较一样,就是变成了内存比较罢了

image-20210912233051911

image-20210912233234287

 //buf1内存里的内容比buf2内存里的内容大就>0,反之<0
 int my_memcmp(const void* buf1, const void* buf2, size_t count)
 {
     assert(buf1 && buf2);
     while (--count && *(char*)buf1 == *(char*)buf2)//这个先减减就是细节
     {
         ((char*)buf1)++;
         ((char*)buf2)++;
     }
     if (*(char*)buf1 - *(char*)buf2 > 0)
         return 1;
     if (*(char*)buf1 - *(char*)buf2 < 0)
         return -1;
     return 0;
 }

给你count不要乱超,因为他操作的是内存,没有字符串补\0的功能

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。