一、引用
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;
}