当前位置:   article > 正文

C语言重点——剖析内存函数memcpy和memmove_memcpy函数会超时吗?

memcpy函数会超时吗?

今天来讲讲,复制内存块函数memcpy和移动内存块函数memmove与字符窜函数的区别。

由于字符窜函数strcpy等只能处理字符窜,面对其他类型时它束手无策。而内存函数很好的弥补了字符窜函数的不足,不管任何类型都可以进行处理。

首先看看内存函数的参数和运行场景:

 我们进行一个实例看看它的结果会怎么样:

  1. #include<stdio.h>
  2. #include<string.h>
  3. int main()
  4. {
  5. int arr1[5] = { 0 };
  6. int arr2[5] = { 1,2,3,4,5 };
  7. memcpy(arr1, arr2, 12);
  8. for (int i = 0; i < 5; i++)
  9. {
  10. printf("%d", arr1[i]);
  11. }
  12. return 0;
  13. }

可以看到给定12字节个数。他就会把源数组arr2起始地址开始里面的12字节拷贝到目标数组arr1里面,比字符窜函数strcpy更强大更牛逼。它只需要拷贝字节数,并不要求是什么类型

那我们不妨自己来模拟实现一下memcpy函数,首先分析memcpy的参数:参数1是传目标起始地址,参数2是传源目标起始地址(参数2进行了const修饰,不允许修改内容),参数三是传需要拷贝的字节数, 返回类型是void*类型,声明部分就分析完了

接着我们分析内部实现:因为传参没有规定类型,所以我们对它进行拷贝的时候最好是一个一个字节的进行拷贝。如:(char *)destination=(char *)source,然后destination往后走一个字节,source往后走一个字节,直到把num个字节都拷贝完。但是我们这儿又不能写成(char *)destination++=(char *)source++,因为强制类型转换在这只是临时的,等后边的++结合的时候又变成void *类型了。所以这儿我们选择用destination=(char *)destination+1和source=(char *)source+1来使他们往后走一个字节。因为还要返回目标的起始地址,所以我们一开始用个指针接收一下。现在分析完了,开始操作实现代码。

  1. #include<stdio.h>
  2. #include<string.h>
  3. #include<assert.h>
  4. void* my_memcpy(void* dest,const void* score,size_t num)
  5. {
  6. assert(dest && score);//因为下面要用指针内部内容,所以判断一下不能是空指针
  7. void * ret = dest;
  8. while (num--)
  9. {
  10. *(char *)dest=*(char *)score;
  11. dest=(char *)dest+1;
  12. score=(char *)score+1;
  13. }
  14. return ret;
  15. }
  16. int main()
  17. {
  18. int arr1[5] = { 0 };
  19. int arr2[5] = { 1,2,3,4,5 };
  20. my_memcpy(arr1, arr2, 12);
  21. for (int i = 0; i < 5; i++)
  22. {
  23. printf("%d", arr1[i]);
  24. }
  25. return 0;
  26. }

运行结果我们可以看到我们自己实现的这个函数和库里面的memcpy一样了。

但是有没有想过这种情况,直接情况+图片展现给大家方便了解

假设有数组 arr[10]={1,2,3,4,5,6,7,8,9,10};

情况:如果我们想把从下标为0位置往后的五个元素复制到从下标为2往后的五个元素会怎么样

我们可以看到并不是我们想要的结果,我们想输出12123458910而它输出的是12121218910.让我们画个图看一下内部到底是因为什么

这时候发现倒着存放就可以避免了。

面对这种时候其实库函数还提供了一个函数叫做memmove内存块移动函数。可以直接实现。

用例展示:

  1. #include<stdio.h>
  2. int main()
  3. {
  4. int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
  5. memmove(arr+2, arr, 20);
  6. for (int i = 0; i < 10; i++)
  7. {
  8. printf("%d", arr[i]);
  9. }
  10. return 0;
  11. }

接着我们自己来看看memmove函数,然后模拟实现一下。

 

现在我们开始实现它,发现只要把第二种的情况补充上就好了。

  1. #include<stdio.h>
  2. #include<assert.h>
  3. #include<string.h>
  4. void* my_mmove(void* dest, void* score, size_t num)
  5. {
  6. void* ret = dest;
  7. assert(dest && score);
  8. if (dest < score)
  9. {
  10. while (num--)
  11. {
  12. *(char*)dest = *(char*)score;
  13. dest = (char*)dest + 1;
  14. score = (char*)score + 1;
  15. }
  16. }
  17. else
  18. {
  19. while (num--)
  20. {
  21. *((char*)dest + num) = *((char*)score + num);
  22. }
  23. }
  24. return ret;
  25. }
  26. int main()
  27. {
  28. int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
  29. my_mmove(arr+2, arr, 20);
  30. for (int i = 0; i < 10; i++)
  31. {
  32. printf("%d", arr[i]);
  33. }
  34. return 0;
  35. }

 

 到这咱们就模拟实现完memmove函数了!

感谢各位朋友的支持!下次再见

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/592466
推荐阅读
相关标签
  

闽ICP备14008679号