user1047069
user1047069

Reputation: 953

implementation of memcpy function

I looked at http://www.opensource.apple.com/source/xnu/xnu-2050.24.15/libsyscall/wrappers/memcpy.c

and didn't understand the following :

1-

inside

void * memcpy(void *dst0, const void *src0, size_t length) {
    char *dst = dst0;
    const char *src = src0;

line:

if ((unsigned long)dst < (unsigned long)src) {

How can we cast dst to an unsigned long ? it's a pointer !

2- Why do they sometimes prefer forward copying and sometimes backwards??

Upvotes: 2

Views: 3029

Answers (2)

Floris
Floris

Reputation: 46365

When comparing a void* and char* pointer, the compiler will give a warning (gcc -Wall):

warning: comparison of distinct pointer types lacks a cast

I imagine that the developer decided to "make the warning go away" - but the correct way to do this is with a void* cast (which is portable):

if((void*) dst < (void*) src) {

As for the second point - as was pointed out, you have to take care of overlapping memory locations. Imagine the following 8 characters in successive memory locations:

 abcdefgh

Now we want to copy this "3 to the right". Starting with a, we would get (with left-to-right copy):

abcdefgh
abcaefgh
   ^
abcabfgh
   ^^
abcabcgh
   ^^^

etc until you end up with

abcabcabcab
   ^^^^^^^^

When we wanted to get

abcabcdefgh

Starting from the other end, we don't overwrite things we still have to copy. When the destination is to the left of the source, you have to do it in the opposite direction. And when there is no overlap between source and destination, it doesn't matter what you do.

Upvotes: 1

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726479

You are right, this implementation is non-portable, because it is assuming that a pointer is going to fit in unsigned long. This is not guaranteed by the standard.

A proper type for this implementation would have been uintptr_t, which is guaranteed to fit a pointer.

Upvotes: 4

Related Questions