void *memcpy(void *dst, void *src, int n)
- 首先该函数是可以复制任意类型的空间的,所以参数是void *
- 再次,源空间src是不可改变的,应该为const void *,但是在考虑重叠的情况下源空间内容是可能被改变的。
- 第三个参数决定了复制的长度
- 要考虑源地址、目的地址、n的有效性
- 要考虑源地址和目的地址重叠的情况,但是重叠的定义又是什么?原则是什么?
- 重叠的情况下如何拷贝?不重叠的情况下又如何拷贝?
- 最后返回dst,不要手贱加上'\0'
重叠:
如果src < dst && src + n > dst,则重叠,要从尾到头拷贝。
如果src < dst && src + n < dst,则不重叠,要从头到尾拷贝。
如果src > dst ,则不重叠!还是可以从头到尾拷贝。
原则:
拷贝之后,不管重叠与否,dst的前n个空间的内容一定是原来src的前n个空间的内容!即使src一定被改变。
Something else:
-
- memcpy未考虑重叠的问题,所以对于重叠是未定义的。。。
- memmove考虑了重叠的问题,所以效率比较低。
代码:
#include <iostream>
#include <cstring>
#include <cassert>
using namespace std;
// without consideration of overlap
void * mymemcpy1(void *dst, void *src, int n){
assert(dst != NULL && src != NULL && n > 0);
char *pdst = (char *)dst;
char *psrc = (char *)src;
while(n--){
*pdst++ = *psrc++;
}
return dst;
}
// 就是要保证复制后,dst的开始n个内容是src的内容
// with consideration of overlap
void * mymemcpy2(void *dst, void *src, int n){
assert(dst != NULL && src != NULL && n > 0);
char *pdst = (char *)dst;
char *psrc = (char *)src;
// overlap, copy from end to start, 重叠,从后往前拷贝
if(psrc < pdst && psrc + n > pdst){
pdst += n - 1;
psrc += n - 1;
while(n--){
*pdst-- = *psrc--;
}
}else{
// no overlap, copy from start to end
while(n--){
*pdst++ = *psrc++;
}
}
return dst;
}
int main(){
char dst1[20] = "abcdefghijk";
char dst2[20] = "abcdefghijk";
cout << "source: " << dst1 << endl;
mymemcpy1(dst1+2, dst1, 5);
cout << "mymemcpy1(no overlap): " << dst1+2 << endl;
mymemcpy2(dst2+2, dst2, 5);
cout << "mymemcpy2(no overlap): " << dst2+2 << endl;
return 0;
}
输出:
source: abcdefghijk
mymemcpy1(no overlap): ababahijk
mymemcpy2(no overlap): abcdehijk