memcpy使用时需要注意的地方

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

猜你喜欢

转载自blog.csdn.net/baidu_35679960/article/details/80953973