首页 > 代码库 > C++面试题4:memcpy的用法

C++面试题4:memcpy的用法


C++面试题4:memcpy的用法

memcpy函数用于把资源内存(src所指向的内存区域)拷贝到目标内存(desk所指向的内存区域);拷贝多少个?有一个size变量控制
用法:可以拷贝任何类型的对象,因为函数的参数类型是void*,也就是说传进去的实参可以是int *,short*,char*等等。
原型:void *memcpy(void *desc, void *src, unsigned int count)
实现memcpy

void *memcpy(void *desc,const void *src,size_t size)
{
    //非法输入
    if(desc == NULL || src =http://www.mamicode.com/= NULL)
    {
        return 0;
    }

    //由于函数拷贝是一个字节一个字节拷贝的,所以要进行类型转换
    unsigned char *desc1 = (unsigned char *)desc;
    unsigned char *src1 = (unsigned char *)src;

    while(size--)
    {
        *desc1=*src1;
        desc1++;
        src1++;
    }
    return desc;
}
这个程序不足的地方在于没有考虑覆盖重叠的情况。如果desc>src但是src+count>desc,我们这个时候复制就一定要注意了。
准确代码.cppvoid *memcpy(void *desc,const void *src, size_t size)
{
    //非法输入
    if(desc == NULL || src =http://www.mamicode.com/= NULL)
    {
        return 0;
    }

    unsigned char *desc1 = (unsigned char *)desc;
    unsigned char *src1 = (unsigned char *)src;

    if(desc1 > src1 && src1 + size > desc)
    {
        for(size_t i = size-1; i >= 0; i--)
        {
            desc1[i]=src1[i];
        }
    }
    else
    {
        for(size_t i = 0; i < n; i++)
        {
            desc1[i]=src1[i];
        }
    }
    return desc;
}

《编写高质量代码:改善C++程序的150个建议》建议20:使用memcpy()系列函数一定要足够小心
memcpy()、memset()、memcmp()等这些内存操作函数经常会帮我们完成一些数据复制、赋值等操作。因为在C语言中,无论是内置类型,还是自定义的结构类型(struct),其内存模型对于我们来说都是可知的、透明的。所以,我们可以对该对象的底层字节序列一一进行操作,简单而有效。
在传统C风格中的数据类型叫做POD对象,即一种古老的纯数据,其二进制内容可以随意复制的,所以我们可以大胆的使用memset()、memcpy()、memcmp()等函数对对象的内存进行操作。
但是在C++中,要注意了,C++对象可能不是一个POD,这是为什么呢?
这就从C++动多态说起,动多态的一个基本支撑技术就是虚函数,在使用虚函数时候,类的每一次继承都会产生一个虚函数表(vtable),其中存放的是指向虚函数的指针,这些虚函数表必须存放在对象体中,也就是和对象的数据内存放在一起,所以对象数据的内存并不是以连续的方式存放的,而是被切割成了不同的部分,既然对象的数据不再集中在一起,如果这个时候使用memcpy,会带来不可以预计的后果。
总结:要区分哪些数据对象是POD,哪些是非POD。由于非POD对象存在,在C++中使用memcpy()系列的函数一定要保持足够小心


C++面试题4:memcpy的用法