原创 memcpy的两种实现(转)

2009-5-1 17:36 5572 7 7 分类: 工程师职场

第一种:最常见的:


void* memcpy( void* dest, const void* src, size_t count )
{


if (count<0)


{printf("Invalid count number !.\n");


return (void*)0;}


if(src==NULL||dest==NULL)


return (void*)0 ;


if ((unsigned int)dest==(unsigned int)src)


{printf("The source is equal with the destanation!.\n");


return dest;}


    char* d = (char*)dest;
    const char* s = (const char*)src;
while(count--)
     *d++ = *s++;
    return dest;
}


 


 


 


 


第二种:转自变态之MEMCPY


void* mymemcpy( void* dest, const void* src, size_t count )
{
    char* d = (char*)dest;
    const char* s = (const char*)src;
    int n = (count + 7) / 8; // count > 0 assumed



    switch( count & 7 )
    {
    case 0: do { *d++ = *s++;
    case 7:        *d++ = *s++;
    case 6:        *d++ = *s++;
    case 5:        *d++ = *s++;
    case 4:        *d++ = *s++;
    case 3:        *d++ = *s++;
    case 2:        *d++ = *s++;
    case 1:        *d++ = *s++;
               } while (--n > 0);
    }


    return dest;
}
解释:摘自原贴:


int n = (count + 7) / 8;计算要复制的轮数(每轮复制8位),剩下的余数位数也要复制进去。
count & 7控制要复制余数位数,while (--n > 0)控制轮数。
比如count = 9,则n = 2,count & 7 = 1,要复制2轮,程序跳到case1执行,复制一位之后,再循环一轮,复制8位.


为何这么实现:引用上面帖子后面的评论:


每8个字节拷贝省7个跳转(AMD处理器内部分支预测算法是“假定全都跳转”,因此这里也就是相当于省了7个时钟周期);把swith和do循环凑到一起,多少省几个字节的空间……
但使用32位或64位指令,可以得到更大的优化效果,代码还要精炼得多。
说实在话:除非内存小到极点、并且无法增加的系统,写出这样的程序纯属作孽……



后记:一般出题目让你实现memcpy,个人理解,其意图至少有以下几点:


1.写任何程序都能反映出你的代码风格.


2.考查你是否注意到,要拷贝的源,即const void* src,应该是用const的,避免有意或无意的修改.


3.考查你,不应该直接对src和dst指针进行类似++或--之类的操作,而应该另外申请对应变量用于此操作.


4.指针的类型转化问题,原始参数应该是void *的,你具体操作的时候,应该是转化为某种具体的类型,此处用char比较适合.


5.注意要判断源src是否和dest重复,如果重复,直接返回或返回错误.


6.应该还有其他考虑,如果以后想到,再补充.


补充:后来又重新看了高质量C++/C编程指南,其中,原作者直接对const char *strSrc和strDest进行++操作


char *strcpy(char *strDest, const char *strSrc);


{


    assert((strDest!=NULL) && (strSrc !=NULL));   // 2分


    char *address = strDest;                     // 2分


    while( (*strDest++ = * strSrc++) != \0 )     // 2分


       NULL ;


    return address ;                           // 2分


}


此时我才注意到,自己总结的上面第三点,是错误的,因为const char *strSrc中的const是指字符串内容为const,而不是说strSrc是const的,如果要指定strSrc是const,应该写成 char * const strSrc 。


不过,对此,有人也许又该问了,那此处对strSrc进行++操作,不是破坏了原先strSrc的指向了吗?


如果你真是这么问,那么说明你的概念还不是很清楚(我开始也是和你犯了同样错误),实际上这点在高质量C++/C编程指南,也有提及,因为strSrc是函数的形参,而此处虽然对形参的进行++ 操作,改变其指向,但是并没有改变原始属性为const的字符串,而且此处的形参,在函数调用结束之后,也就释放了,对原始传来的地址,没有任何影响。


 


 


 


返回void*是为了方便,可以直接放在其他的函数里连续调用。


如:memcpy(memcpy(BufDet, BufSrc1, SIZE(BufSrc1)), BufSrc2,SIZE(BufSrc2));

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
我要评论
0
7
关闭 站长推荐上一条 /4 下一条