Linux实现memcpy

本文介绍了一种高效的内存拷贝函数Memcpy,考虑了地址重叠问题,特别是向后重叠的情况,并以8字节为单位优化拷贝效率,同时适应32位和64位机器的数据结构差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、引用 

1.linux C编程:重写 memcpy 函数_memcpy_fromio_老王不让用的博客-优快云博客

2.实现一个高效率的内存拷贝函数memcpy_高效 内存复制函数_wykup的博客-优快云博客

        以上两篇博客提供了很大思路,但是考虑到实际面试当中的时间等问题,结合以上两篇实现如下代码

//max_dest_len:接收buff的最大长度
//count:需要拷贝的字节长度
void *Memcpy(void *dest, size_t max_dest_len, const void *src, size_t count)  
{  
    int nbyte      = sizeof(long long);
	int byte8count =count/nbyte;	/*按每次8字节拷贝*/
	int byte1count =count%nbyte;	/*剩余的按字节拷贝*/
	long long* ds  = (long long*)dest;  
    long long* ss  = (long long*)src;  
    char * dts     = NULL;
	char * sts     = NULL;
    
    if(max_dest_len < count)
        return ;

    if((dest > src) && (dest < src+count)) //地址向后重叠
    {
        ds = (long long *)((long long)dest +count-nbyte);
        ss = (long long *)((long long )dest +count-nbyte);
        
        while(byte8count--) 
            *ds-- = *ss--;
        
        ds++;ss++;
        dts = (char *)ds;
        sts = (char *)ss;
        while(byte1count--)
        {
            *(char *)dts-- = *(char *)sts--; 
        } 
    }else{ //地址向前重叠或者不重叠
        while (byte8count--)
            *ds++ = *ss++;

        dts = (char *)ds;
        sts = (char *)ss;
        while (byte1count--)
            *(char *)dts++ = *(char *)sts++;   
    }

    return dest;  
}  

此代码可运行

核心思路(兼顾时间、实现难度等):

1.地址重叠,主要考虑向后重叠

2.效率,这里是以8字节的方式去拷贝

3.32位和64位机器数据结构所占字节的区别

#include <stdio.h>
#include <string.h>

typedef     unsigned char           u8;
typedef     unsigned short          u16;
typedef     unsigned int            u32;
typedef     unsigned long long      u64;

#define     U8_LEN                   1
#define     U16_LEN                  2
#define     U32_LEN                  4
#define     U64_LEN                  8


inline void 
memcpy8(void *dst, const void *src){
    *(u64 *)dst = *(u64 *)src;
}

inline void 
memcpy4(void *dst, const void *src){
    *(u32 *)dst = *(u32 *)src;
}

inline void 
memcpy2(void *dst, const void *src){
    *(u16 *)dst = *(u16 *)src;
}

inline void 
memcpy1(void *dst, const void *src){
    *(u8 *)dst = *(u8 *)src;
}

inline void 
memcpy16(void *dst, const void *src)
{
    memcpy8(dst, src);
    memcpy8(dst+U64_LEN, src+U64_LEN);
}

inline void 
memcpy32(void *dst, const void *src)
{
    memcpy16(dst, src);
    memcpy16(dst+16, src+16);
}

inline void 
memcpy64(void *dst, const void *src)
{
    memcpy32(dst, src);
    memcpy32(dst+32, src+32);
}

int 
memcpy_fast(void *dst, void *src, size_t dst_n, size_t src_n)
{
    size_t n = src_n;
    u8 *d = dst, *s = src;

    if(dst_n > src_n)
        return -1;
    
    if(!src_n)
        return -1;

    while(n > 0){
        if(n > U64_LEN){
            memcpy8(d, s);
            d += U64_LEN, s += U64_LEN;
            n -= U64_LEN;
        }else if(n > U32_LEN){
            memcpy4(d, s);
            d += U32_LEN, s += U32_LEN;
            n -= U32_LEN;
        }else if(n > U16_LEN){
            memcpy2(d, s);
            d += U16_LEN, s += U16_LEN;
            n -= U16_LEN;
        }else{
            memcpy1(d, s);
            d += U8_LEN, s += U8_LEN;
            n -= U8_LEN; 
        }
    }

    return dst_n;
}

int main(int argc, char *argv[])
{
    char src[1024] = "200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
    char dst[1024] = {'\0'};
    int ret = memcpy_fast(dst, src, (size_t)strlen(src), 1024);

    printf("dst:%s, ret = %d\n",dst, ret);

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

QQ851301776

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值