[经典面试题]实现memcpy库函数

【题目】

已知memcpy的函数为: void* memcpy(void *dst , const void* src , size_t count)

其中dst是目的指针,src是源指针。不调用c++/c的memcpy库函数,请编写memcpy。


-------百度,网新恒天校园招聘

【解析】

1 按照ANSI(American National Standards Institute)标准,不能对void指针进行算法操作,

即不能对void指针进行如p++的操作,所以需要转换为具体的类型指针来操作,例如char *

2 memcpy是对内存进行操作,可能遇到内存重叠的情况,同样的问题存在于memmove中, 但是源代码中这两个函数的处理方式不一样:

memcpy中dst和src中的区域不能重叠,否则会出现未知结果。函数没做任何内存的处理,内存是否重叠由程序员自己控制。

memmove里面则判断了内存重叠的情况,当内存重叠时从后往前复制,以确保复制正常处理。

【代码】

#include <iostream>
using namespace std;

//实现memcpy库函数
void* memcpy(void *dst, const void *src, size_t count){
    // 容错处理
    if(dst == NULL || src == NULL){
        return NULL;
    }
    unsigned char *pdst = (unsigned char *)dst;
    const unsigned char *psrc = (const unsigned char *)src;
    //判断内存是否重叠
    bool flag1 = (pdst >= psrc && pdst < psrc + count);
    bool flag2 = (psrc >= pdst && psrc < pdst + count);
    if(flag1 || flag2){
        cout<<"内存重叠"<<endl;
        return NULL;
    }
    // 拷贝
    while(count--){
        *pdst = *psrc;
        pdst++;
        psrc++;
    }
    return dst;
}

int main(){
    char c1[] = "hello world";
    memcpy(c1+3, c1, 9);
    cout<<"memcpy result:"<<c1<<endl;
    char c2[] = "love you";
    memcpy(c1,c2,8);
    cout<<"memcpy result:"<<c1<<endl;
}


#include <iostream>
#include <string.h>
using namespace std;

//实现memmove库函数
void* memmove(void *dst, const void *src, size_t count){
    // 容错处理
    if(dst == NULL || src == NULL){
        return NULL;
    }
    unsigned char *pdst = (unsigned char *)dst;
    const unsigned char *psrc = (const unsigned char *)src;
    //判断内存是否重叠
    bool flag1 = (pdst >= psrc && pdst < psrc + count);
    bool flag2 = (psrc >= pdst && psrc < pdst + count);
    if(flag1 || flag2){
        // 倒序拷贝
        while(count){
            *(pdst+count-1) = *(psrc+count-1);
            count--;
        }//while
    }
    else{
        // 拷贝
        while(count--){
            *pdst = *psrc;
            pdst++;
            psrc++;
        }//while
    }
    return dst;
}

int main(){
    // 内存重叠
    char c1[] = "hello world";
    memmove(c1+3, c1, 8);
    cout<<"memmove result:"<<c1<<endl;
    // 内存不重叠
    char c2[] = "hello world";
    char c3[] = "love you";
    memmove(c2,c3,8);
    cout<<"memmove result:"<<c2<<endl;
}


#include <iostream>
using namespace std;

void* memmove(void* str1,const void* str2,size_t n){
    char* pStr1= (char*) str1;
    const char* pStr2=(const char*)str2;
    // 正序拷贝
    if  (pStr1  < pStr2) {
        for(size_t i=0;i!=n;++i){
            *(pStr1++)=*(pStr2++);
        }
    }
    // 倒序拷贝
    else{
        pStr1+=n-1;
        pStr2+=n-1;
        for(size_t i=0;i!=n;++i){
            *(pStr1--)=*(pStr2--);
        }
    }
    return pStr1;
}


int main(){
    char str[] = "hello world";
    memmove(str+4,str,7);
    cout<<str<<endl;
    return 0;
}




上一篇:坏消息!FCC默许美国ISP在未经批准之情况下出售用户数据!


下一篇:[LintCode] 最长公共子序列