变态的命名
我们在写程序时,一般讲究见到变量的命名,就能让别人基本知道该变量的含义。memcpy内存拷贝,没有问题;memmove,内存移动?错,如果这样理解的话,那么这篇文章你就必须要好好看看了,memmove还是内存拷贝。那么既然memcpy和memmove二者都是内存拷贝,那二者究竟有什么区别呢?
先说memcpy
你有没有好好的参加过一场C++笔试。让你写出memcpy的实现,这是多么常见的笔试题啊。现在,拿起你的演算纸和笔;是的,是笔和纸,不是让你在你的IDE上写。写不出来?看下面吧:
void *mymemcpy(void *dest, const void *src, size_t count) { assert(dest != NULL || src != NULL); char *tmp = (char *)dest; char *p = (char *)src; while (count--) { *tmp++ = *p++; } return dest; }
memcpy的实现很简单,一般在笔试时,出现写源码的题目,无非就是需要注意以下几点:
1.确定函数原型;
2.判断参数合法性;
3.逻辑实现(考虑各种情况,统称逻辑实现);
4.错误处理。
当然了,我的这个没有错误处理,也不需要错误处理。上面,我写出了memcpy的实现源码,实现原理如下图所示:
这样下去,上面的代码会运行的很好,如果出现下面的情况呢?
i、n、k的内存和J、e、l的内存地址重合了,现在再使用上面的代码进行copy时,会出现什么问题呢?你有没有想过这个问题。如果没有,那就现在想想,不急着阅读下面的内容。
然后,我再留一个问题,上面的代码中,为什么都需要将void *转换成char *呢?比如:
char *tmp = (char *)dest;
可以留言回答哦。
再说memmove
memmove也是用来实现内存的直接拷贝的。说起这个命名,我个人觉的多少还是有点坑的。既然memmove也是用来内存数据移动的,那就先来看看memmove的实现源码。
void *mymemmove(void *dest, const void *src, size_t count) { assert(dest != NULL || src != NULL) if (dst < src) { char *p = (char *)dest; char *q = (char *)src; while (count--) { *p++ = *q++; } } else { char *p = (char *)dest + count; char *q = (char *)src + count; while (count--) { *--p = *--q; } } return dest; }
从源码看,memmove的确比memcpy复杂一些;再仔细一看,多了些什么?哦,多了一个else分支,而正是这个else分支,就处理了当src和dest的内存重合的问题。
memcpy和memmove的比较
从实现源码中的确能看出一些猫腻,当出现了src和dest的内存有重合的时机时,memmove的处理规则是从后往前进行copy。当然了,重合的问题,需要考虑的以下两种场合。
如图所示,当出现(1)对应的情况时,就需要先从src的头部开始复制;也就是memmove源码中的if分支,这部分源码和memcpy的实现是一致的;当出现(2)对应的情况时,就需要先从src的尾部开始复制,防止出现了覆盖现象。这就是memmove比memcpy多的一个考虑点,所以说,在实际使用时,使用memmove是比memcpy更安全的。
总结
总结到了这里,我觉的我已经把问题说清楚了。你说呢?如果你还有什么好的想法,欢迎你和我分享。
本文向大家介绍C#中new和override的区别个人总结,包括了C#中new和override的区别个人总结的使用技巧和注意事项,需要的朋友参考一下 问题: A类 有方法 public virtual void test() B类继承自A类,有方法 public new void test() 如下实例化: 会调用哪个类中的TEST方法,最好能详细给我解释一下好吗?先谢谢了! 回答: 如果你用
本文向大家介绍C / C ++中的memcpy(),包括了C / C ++中的memcpy()的使用技巧和注意事项,需要的朋友参考一下 在本文中,我们将讨论C ++ STL中函数的工作,语法和示例。 什么啊 memcpy()函数是C ++ STL中的内置函数,在<cstring>头文件中定义。函数用于复制内存块。此功能用于将值的数量从一个存储位置复制到另一个存储位置。 该函数的结果是数据的二进制副
本文向大家介绍C# 中 &和&&的区别相关面试题,主要包含被问及C# 中 &和&&的区别时的应答技巧和注意事项,需要的朋友参考一下 答: &是位运算符,表示按位与运算,&&是逻辑运算符,表示逻辑与(and).
本文向大家介绍C / C ++中float和double的区别,包括了C / C ++中float和double的区别的使用技巧和注意事项,需要的朋友参考一下 众所周知,在C / C ++中,我们需要float和double数据类型来表示浮点数,即带有小数部分的数字。现在,根据这两种数据类型提供的精度,我们可以区分两者 其中。 简而言之,可以说double的精度是float的2倍,这意味着doub
本文向大家介绍ASP.NET中Session和Cache的区别总结,包括了ASP.NET中Session和Cache的区别总结的使用技巧和注意事项,需要的朋友参考一下 以前实现数据的缓存有很多种方法,有客户端的Cookie,有服务器端的Session和Application。其中Cookie是保存在客户端的一组数据,主要用来保存用户名等个人信息。Session则保存对话信息。Application
本文向大家介绍Redis和Memcache的区别总结,包括了Redis和Memcache的区别总结的使用技巧和注意事项,需要的朋友参考一下 总结一: memcache官方定义 Free & open source, high-performance, distributed memory object caching system, generic in nature, but intended
本文向大家介绍C#中Action和Func的区别,包括了C#中Action和Func的区别的使用技巧和注意事项,需要的朋友参考一下 本文实例分析了C#中Action和Func的区别,有助于读者牢固掌握并对其准确使用。具体分析如下: 先来看下面这段代码: 主要区别: Func<t, Result> 封装一个具有一个参数并返回 TResult 参数指定的类型值的方法。 Action<t> 封装一个方
本文向大家介绍C#中堆和栈的区别?相关面试题,主要包含被问及C#中堆和栈的区别?时的应答技巧和注意事项,需要的朋友参考一下 答 栈:由编译器自动分配、释放。在函数体中定义的变量通常在栈上。 堆:一般由程序员分配释放。用new、malloc等分配内存函数分配得到的就是在堆上。 存放在栈中时要管存储顺序,保持着先进后出的原则,他是一片连续的内存域,有系统自动分配和维护; 堆是无序的,他是一片不连续