Article View: comp.std.c
Article #1736Re: memcpy
From: James C Burley
Date: Fri, 21 Sep 1990 15:12
Date: Fri, 21 Sep 1990 15:12
82 lines
3270 bytes
3270 bytes
In article <13914@smoke.BRL.MIL> gwyn@smoke.BRL.MIL (Doug Gwyn) writes:
... Some memcpy() implementations
have attempted to "do the right thing" (meaning: follow the sequential
pick-the-entire-block-up-into-a-temporary-register, then-put-the-
temporary-register-contents-back-down-at-the-new-location model) for
cases of overlaps, while others have not.
First off, it strikes me (THUNK! :-) that my expectation of what memmove
would do is exactly the opposite of what is desired. If one wants to use
a memory move to spew a given set of values (in the case discussed here,
just one) across memory, and indeed the more-than-one case is not covered
to my knowledge my memset or any other ANSI function, it seems that one does
not want to use a memory move that is "smart enough" to do an overlapping
move the "right" way. If I have
char array[5] = [ 1, 2, 3, 4, 5 ];
and I memmove 4 bytes from array[0] to array[1], personally I would expect
the more natural result to be:
[ 1, 1, 2, 3, 4 ]
But the original posting seems to be asking for
[ 1, 1, 1, 1, 1 ]
Similarly, taking the original array and memmoving (sigh) 4 bytes from
array[1] to array[0], I'd think one should get:
[ 2, 3, 4, 5, 5 ];
But again someone else might want:
[ 5, 5, 5, 5, 5 ];
So I read the statement "memmove handles overlapping copies correctly" to
mean what is stated above in the reference posting I've included: the copy
happens AS IF the source array were copied into a temporary, then copied
into the destination. What the original posting appears to ask for is a
copy that does the "wrong" thing.
Second, I don't think it is necessary for memmove to actually copy into a
temporary. I think one can do an implementation similar to the following
(I've probably made a couple of mistakes, but you get the idea):
void *memmove(void *source,void *dest,size_t n)
{
void *save;
/* Let's not bother with (char *) casts, ok? (-: Actually the copies can
be done using casts to int * or long * if the proper modulo checking is
done, for efficiency. */
if ((source == dest) || (n == 0))
return source; /* Nothing to do. */
save = source;
if ((source > dest) || (source + n <= dest))
{ /* Normal case: source follows destination, or no overlap at all. */
for (; n != 0; n--)
*dest++ = *source++;
return save;
}
/* The source array precedes and overlaps with the destination array, so
copy the array backwards. */
source += n;
dest += n;
for (; n != 0; n--)
*--dest = *--source;
return save;
}
This should get the idea across, but probably contains silly mistakes besides
the omission of casts!
James Craig Burley, Software Craftsperson burley@world.std.com
Technical Details
Message-ID:
<BURLEY.90Sep21111221@world.std.com>Path:
arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!uunet!world!burleyReferences:
<1990Sep19.021418.11574@maths.tcd.ie> <13914@smoke.BRL.MIL>Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!uunet!world!burley From: burley@world.std.com (James C Burley) Newsgroups: comp.std.c Subject: Re: memcpy Message-ID: <BURLEY.90Sep21111221@world.std.com> Date: 21 Sep 90 15:12:21 GMT References: <1990Sep19.021418.11574@maths.tcd.ie> <13914@smoke.BRL.MIL> Sender: burley@world.std.com (James C Burley) Organization: The World Lines: 82 In-Reply-To: gwyn@smoke.BRL.MIL's message of 20 Sep 90 21:26:59 GMT