最近在论坛上看了一篇关于阿里巴巴面试题的帖子,让自己实现memcpy库函数,要求考虑特殊情况,两段内存存在覆盖,以及指针为空的情况。下面是我对此问题的几点看法(可能还有理解不到的地方)和最终修改的代码。
几点结论:
1,memcpy实现从源source中拷贝n个字节到目标destin中,src源数据应该保留。
2,memmove实现移动一块字节,src源数据可以不保留。
3,memcpy没有考虑内存覆盖问题(由assert条件可知);而memmove考虑了内存覆盖问题,并给出了解决办法。
4,memcpy和memmove中不需要考虑数组越界问题,dst的长度应该大于src的长度,这是调用者应该考虑的问题。
- /*
- * 函数名: memcpy
- * 功 能: 从源source中拷贝n个字节到目标destin中
- * 用 法: void *memcpy(void* destin, const void* source, size_t n);
- * 说 明: 自己实现此库函数
- */
- #include <stdio.h>
- //#include <string.h>//memcpy库函数头文件
- #include <conio.h> //getch头文件
- #include <assert.h> //assert头文件
- typedef unsigned char byte;
- //typedef unsigned int size_t;
- /*
- memcpy自定义函数
- */
- //src要保留
- void* memcpy(void* dst,const void* src,size_t count)
- {
- char* pbTo = (char*)dst;
- char* pbFrom = (char*)src;
- assert(dst!= NULL && src != NULL);//不能存在空指针
- assert(pbTo >= pbFrom+count || pbFrom >= pbTo + count);//防止内存重叠(overlap)
- while (count-- > 0)
- {
- *pbTo++ = *pbFrom++;
- }
- return dst;
- }
- /*
- memmove自定义函数
- */
- //src可以不保留
- void* memmove(void* dst,const void* src,size_t count)
- {
- char* pbTo = (char*)dst;
- char* pbFrom = (char*)src;
- assert(dst != NULL && src != NULL);//不能存在空指针
- if (dst <= src || pbTo >= pbFrom + count)//没有overlap的情况,直接拷贝
- {
- while (count-- > 0)
- {
- *pbTo++ = *pbFrom++;
- }
- }
- else
- {
- pbTo = pbTo + count -1;//overlap的情况,从高位地址向低位拷贝
- pbFrom = pbFrom + count -1;
- while (count-- > 0)
- {
- *pbTo-- = *pbFrom--;
- }
- }
- return dst;
- }
- int main()
- {
- char src[]="*********";
- char dst[]="abcdefghijklmnopqrstuvwxyz";
- char *ptr;
- printf("destination before memcpy: %s/n",dst);
- //测试用例1
- ptr=(char *)memcpy(dst,src,sizeof(src)/sizeof(char));
- //测试用例2
- //ptr=(char *)memmove(dst,src,sizeof(src)/sizeof(char));
- //测试用例3
- //ptr=(char *)memcpy(dst+1,dst,2);//memcpy没有考虑内存覆盖,如果出现覆盖assert报错
- //测试用例4
- //ptr=(char *)memmove(dst+1,dst,2);//memmove考虑了内存覆盖
- if (ptr)
- {
- printf("destination after memcpy: %s/n",ptr);
- }
- else
- {
- printf("memcpy failed/n");
- }
- getch();
- return 0;
- }
修改用例测试:
- /*
- Modification Date: 2010-3-17
- Author: wcdj
- */
- #include <cstdio>
- #include <string.h> // memcpy库函数头文件
- #include <conio.h> // getch头文件
- #include <assert.h> //assert头文件
- typedef unsigned char byte;
- //typedef unsigned int size_t;
- /*
- memcpy自定义函数
- */
- //src要保留
- void* memcpy(void* dst,const void* src,size_t count)
- {
- char* pbTo = (char*)dst;
- char* pbFrom = (char*)src;
- assert(dst!= NULL && src != NULL);//不能存在空指针
- assert(pbTo >= pbFrom+count || pbFrom >= pbTo + count);//防止内存重叠(overlap)
- while (count-- > 0)
- {
- *pbTo++ = *pbFrom++;
- }
- return dst;
- }
- /*
- memmove自定义函数
- */
- //src可以不保留
- void* memmove(void* dst,const void* src,size_t count)
- {
- char* pbTo = (char*)dst;
- char* pbFrom = (char*)src;
- assert(dst != NULL && src != NULL);//不能存在空指针
- if (dst <= src || pbTo >= pbFrom + count)//没有overlap的情况,直接拷贝
- {
- while (count-- > 0)
- {
- *pbTo++ = *pbFrom++;
- }
- }
- else
- {
- pbTo = pbTo + count -1;//overlap的情况,从高位地址向低位拷贝
- pbFrom = pbFrom + count -1;
- while (count-- > 0)
- {
- *pbTo-- = *pbFrom--;
- }
- }
- return dst;
- }
- int main()
- {
- // test
- char src[]="123456";
- char dst[]="abcdefghijklmnopqrstuvwxyz";
- char *ptr;
- printf("destination before memcpy: %s/n",dst);
- //测试用例1
- ptr=(char *)memcpy(dst,src,sizeof(src)/sizeof(char));// "123456"
- //ptr=(char *)memcpy(dst,src,strlen(src));// "123456ghijklmnopqrstuvwxyz"
- //测试用例2
- //ptr=(char *)memmove(dst,src,sizeof(src)/sizeof(char));// "123456"
- //ptr=(char *)memmove(dst,src,strlen(src));// "123456ghijklmnopqrstuvwxyz"
- //测试用例3
- //ptr=(char *)memcpy(dst+1,dst,2);//memcpy没有考虑内存覆盖,如果出现覆盖assert报错
- //测试用例4
- //ptr=(char *)memmove(dst+1,dst,2);//memmove考虑了内存覆盖 "abde...z"
- if (ptr)
- {
- printf("destination after memcpy: %s/n",ptr);
- }
- else
- {
- printf("memcpy failed/n");
- }
- getch();
- return 0;
- }