🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.std.c
Article #1736

Re: memcpy

#1736
From: James C Burley
Date: Fri, 21 Sep 1990 15:12
82 lines
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!burley
References: <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