memcpy使用时需要注意的地方

xiaoxiao2021-02-28  25

测试平台:codeblocks 17.12;

1、注意最后一个参数是字节数;

原型:

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,

这才是我们想要的!

2、注意内存重叠的问题

在很久很久以前,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

转载请注明原文地址: https://www.6miu.com/read-2627341.html

最新回复(0)