Implementing an Optimized Memmove in C

348 Views Asked by At

I am trying to implement my own memmove function. I am trying to optimize it instead of copying byte by byte. Here is my implementation:

void* my_memmove(void *dest, const void *src, size_t len) {
    
    if((uintptr_t)dest < (uintptr_t)src)
        return memcpy(dest,src,len);
    
    long *pdest = (long*)dest +len;
    const long *psrc = (const long*)src+len;
    
    if(!((uintptr_t)dest+len & (sizeof(long)-1)) &&
      !((uintptr_t)src+len & (sizeof(long)-1))) {
        
        while(len >= sizeof(long)) {
            *--pdest = *--psrc;
            len-=sizeof(long);
        }
    }
    
    char *pdest2 = (char*)pdest;
    const char *psrc2= (const char*)psrc;
    
    while(len) {
        *--pdest2 = *--psrc2;
        len--;
    }
    
    return dest;
}

Any input on how I can make this better or if the existing code has some issues?

1

There are 1 best solutions below

3
Support Ukraine On

There is a bug in the code calling memcpy.

I changed your code like

void* my_memmove(void *dest, const void *src, size_t len) {
    
    if((uintptr_t)dest < (uintptr_t)src)
    {
        printf("memcpy\n");
        return memcpy(dest,src,len);
    }
    
    printf("my code\n");
    return NULL;
}

int main() 
{
   unsigned char a[100] = {0};
   my_memmove(&a[0], &a[25], 50);  // Overlapping dst and src
   return 0;
}

Output:

memcpy

So you call memcpy with overlapping areas.

Another bug...

What do you expect from this line:

long *pdest = (long*)dest +len;

Assume dest is 0x1000 and len is 1. It seems you expect the value 0x1001 but try this:

int main() 
{
    size_t len = 1;
    long *pdest = (long*)0x1000 +len;
    printf("%p\n", (void*)pdest);
    
   return 0;
}

Output on my system:

0x1008

which is not what you want.