memcpy是把source 指向的对象中的n个字符拷贝到destin所指向的对象中,返回指向结果对象的指针。
memmove也是把source 指向的对象中的n个字符拷贝到destin所指向的对象中,但过程就好象是先把source所指向的 对象拷贝到临时数组中,然后在从临时数组拷贝到destin所指的对象中,返回指向结果对象的指针。
但要注意,除memmove之外的字符串操作函数在拷贝同一个字符串中的字符时,其结果是不确定的。也就是说,memmove 可以把自己的一部分拷贝给自己的另一部分。其他函数不行,比如memcpy(事实上也是可行的,MSDN里的例子就没问题,暂且不管 他了)。
先看memcpy的,没什么很特别的,咱们都会:
- /**
- * memcpy - Copy one area of memory to another
- * @dest: Where to copy to
- * @src: Where to copy from
- * @count: The size of the area.
- *
- * You should not use this function to access IO space, use memcpy_toio()
- * or memcpy_fromio() instead.
- */
- void * memcpy ( void * dest, const void *src, size_t count)
- {
- char *tmp = ( char *) dest, *s = ( char *) src;
- while (count--)
- *tmp++ = *s++;
- return dest;
- }
但据说运行库里memcpy是用汇编写的,运行快,看到的.c代码文件都是象征性代码!
再看看memmove是怎么实现的,如果让我们实现memmove功能,我想很多人会像我最初的想法一样,先做一个拷 贝吧?我们看看Linux内核里是怎么实现的:
- /* Normally compiler builtins are used, but sometimes the compiler calls out
- of line code. Based on asm-i386/string.h.
- */
- #define _STRING_C
- #include <linux/string.h>
- #undef memmove
- void *memmove ( void * dest, const void *src, size_t count)
- {
- if (dest < src) {
- __inline_memcpy(dest,src,count);
- } else {
- char *p = ( char *) dest + count;
- char *s = ( char *) src + count;
- while (count--)
- *--p = *--s;
- }
- return dest;
- }
紫色的代码 : 如果源地址与目标地址的拷贝不存在覆盖问题,则直接用memcpy,在内核层面上尽可能重用代码是应该必须的!但这很同样 值得我们去反思我们平时的代码,到处充斥着功能相同或近似的代码,那天突然发现了bug,就得从头到尾去找那些用相同思想写出来的拷 贝,这是一种折磨,我保证!因为我经历过,并且很多时候由于没有事先构建好程序架构而当编了上千行代码后又懒得抽取那些功 能相似的代码作为函数,总想着没多少了,就这样吧...这样写出来的代码大家可想而知,debug和维护起来将是灾难,我 只能祈祷那些东西不要出什么乱子,最好也不用再更新吧,各位借鉴!
红色的代码 : 为我们最开始的先做个拷贝的想法哀悼了吗?我是自惭了!
这是多么漂亮而巧妙的代码
,前序遍历会出现重叠问题转而用后序遍历很巧妙的省去了一个拷贝,学习学习