Reputation: 953
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
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
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