测试平台:codeblocks 17.12;
原型:
void * memcpy ( void * destination, const void * source, size_t num );将source指向的地址处的 num 个字节 拷贝到 destination 指向的地址处。注意加黑的字,是字节。 例如:
int a[10] = {0,1,2,3,4,5,6,7,8,9}; memcpy(a, a + 3, 2);你猜拷贝过之后a数组的值是什么?
3,4,2,3,4,5,6,7,8,9,
是这样么?
不是!
真实结果是: 3,1,2,3,4,5,6,7,8,9,
为什么?
因为memcpy的最后一个参数是需要拷贝的字节的数目!一个int类型占据4个字节!这样的话,要想达到将a+3地址开始的2个元素拷贝到a地址处,需要这么写:
memcpy(a, a + 3, 2*sizeof(int));经过这么一条语句,a数组的内容就变成了: 3,4,2,3,4,5,6,7,8,9,
这才是我们想要的!
在很久很久以前,memcpy的实现大致是这样的:
void* my_memcpy(void* dst, const void* src, size_t n) { char *tmp = (char*)dst; char *s_src = (char*)src; while(n--) { *tmp++ = *s_src++; } return dst; }这样的话,当你执行下面的程序时:
#include <iostream> #include <cstring> using namespace std; void* my_memcpy(void* dst, const void* src, size_t n) { char *tmp = (char*)dst; char *s_src = (char*)src; while(n--) { *tmp++ = *s_src++; } return dst; } int main() { int a[10] = {0,1,2,3,4,5,6,7,8,9}; my_memcpy(a + 3, a, 5*sizeof(int)); int i = 0; for(int i = 0; i < 10; i++){ printf("%d,", a[i]); //0,1,2,0,1,2,0,1,8,9, } return 0; }猜猜输出是什么?
或许我们想要达到的效果是:0,1,2,0,1,2,3,4,8,9, 这样?
NO!
真实的输出是: 0,1,2,0,1,2,0,1,8,9,
这是因为原地址和目的地址这两段有重叠,导致了如上的输出结果;
现在的memcpy都做了改进,能够达到和memmove一样的效果,即使在目的地址和原地址存在重叠时也能达到我们想要的结果。 即:
#include <iostream> #include <cstring> using namespace std; int main() { int a[10] = {0,1,2,3,4,5,6,7,8,9}; memcpy(a + 3, a, 5*sizeof(int)); //memmove(a + 3, a, 5*sizeof(int)); 也行; int i = 0; for(int i = 0; i < 10; i++){ //0,1,2,0,1,2,3,4,8,9, printf("%d,", a[i]); } return 0; }参考:https://my.oschina.net/zidanzzg/blog/812887
