C语言中的内存函数有如下这些

  • memcpy
  • memmove
  • memcmp
  • memset

下面看看memmove函数

memmove

为什么会需要memmove函数?

int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int i = 0;
// 想把12345 拷贝到 34567上去
// 应该打印 1 2 1 2 3 4 5 8 9 10
my_memcpy(arr + 2, arr, 20); for (i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
// 但是输出 1 2 1 2 1 2 1 8 9 10 return 0;
}

上面会输出 1 2 1 2 1 2 1 8 9 10,我们来看看为什么会出现这样的结果。

我这里画了张图,方便理解。

因为拷贝的地方重叠了,使原来的数据(3 4 5)被覆盖了,导致最后出来的结果不是我们想要的。

也就是说,如果拷贝的地方重叠了,那么就会出现这种情况。

那么如何解决呢?答案就是从后往前拷贝,指针从最后的地方开始操作。

还是上一张图

这样,就得出了我们想要的结果。

但是呢,也不能一概而论,就全部都是从后往前拷贝,还是得分情况的,具体就是看destinationsource的位置关系。

回到最开始的问题,为什么会需要memmove函数?,因为memmove这个函数可以处理这种重叠拷贝。

老规矩,我们还是看看文档是怎样说的,如下

memmove文档

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

Move block of memory

移动内存块(移动内存数据)

Copies the values of num bytes from the location pointed by source to the memory block pointed by destination. Copying takes place as if an intermediate buffer were used, allowing the destination and source to overlap.

从source(源内存块位置)直接指向的地方开始复制num个字节的数据到destination指向的内存块位置。然后复制就像使用了中间缓冲区一样,允许destination和source重叠。

The underlying type of the objects pointed by both the source and destination pointers are irrelevant for this function; The result is a binary copy of the data.

这句话没看懂,不影响我们学这个。

The function does not check for any terminating null character in source - it always copies exactly num bytes.

这个函数不会检查'\0',不会遇到'\0'就停下来,它就只认识要复制的num个字节数据。

To avoid overflows, the size of the arrays pointed by both the destination and source parameters, shall be at least num bytes.

为了避免溢出,这两个数组的大小至少为num个字节。

可以看出,memmove和memcpy的唯一区别就是,memmove函数处理的源内存块和目标内存块是可以重叠的。

也就是说,如果源空间和目标空间出现重叠,就得使用memmove函数处理。

实现

断言指针不为空是个好习惯~

void* my_memmove(void* dest, void* src, size_t num)
{
//dest落在了src的左边,从前往后拷贝
//dest落在了src的右边,同时没有超过那个重叠的边界的时候,从后往前拷贝
assert(dest != NULL);
assert(src != NULL);
void* rest = dest;
// void* 不能直接解引用,那么如何复制呢?
// 给了num个字节,也就是需要复制num个字节
// 那就转换成char*,一个一个字节的复制过去
if (dest < src)
//if (dest < src || dest > (char*)src + num)
{
//dest落在了src的左边,从前往后拷
while (num--)
{
*(char*)dest = *(char*)src;
//++(char*)dest;
//++(char*)src;
((char*)dest)++;
((char*)src)++;
}
}
else
{
// 从后往前拷
// 找到最后一个字节
while (num--)
{
*((char*)dest + num) = *((char*)src + num);
} }
return rest;
}

最后,感谢屏幕前靓仔花宝贵的时间阅读我这篇博客~

本人水平有限,如有错误以及不足之处,欢迎靓仔指出。

最新文章

  1. Javascript本质第二篇:执行上下文
  2. 安装php-amqplib(RabbitMQ的phpAPI)
  3. oracle的游标
  4. 8.springMVC中的RESTful架构风格
  5. Android 之 2048 的游戏逻辑分析
  6. C++ 之 常量成员函数
  7. Linux的五个查找命令(find、locate、whereis、which、type)
  8. 优化有标量子查询的SQL
  9. C# 将MSMQ消息转换成Json格式 【优化】
  10. [React] React Router: Querystring Parameters
  11. HLS 协议
  12. 彻底搞清函数中的this指向
  13. JavaScript遍历对象-总结一
  14. Sublime 安装、插件CoolFormat
  15. python字符串与数字类型转化
  16. Nginx 配置 https
  17. centos7下安装docker(2镜像)
  18. 微软Power BI 每月功能更新系列——10月Power BI 新功能学习
  19. 记录:CSS特殊性——权值规则
  20. $.AJAX参数提交及后台获取方式

热门文章

  1. 如何使用 Navicat Premium 的新“自动运行”工具自动运行行数据库复制。
  2. 操作系统---IO权限管理和敏感指令
  3. PAT-1066(Root of AVL Tree)Java语言实现
  4. .NET CORE 3.1 MVC Log4net
  5. layui数据表格-通过点击按钮使数据表格中的字段值增加
  6. Python3+pygame实现的flappy bird游戏,代码完整,还有音乐
  7. 两种常见Content-type的方便理解
  8. I - Tetrahedron HDU - 6814
  9. LookupError: &#39;hex&#39; is not a text encoding; use codecs.decode() to handle arbitrary codecs
  10. 92反转链表II