测试平台: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
#include
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
#include
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