[comp.lang.c] memcpy vs. memmove

scs@athena.mit.edu (Steve Summit) (09/13/88)

In article <8389@smoke.ARPA> gwyn@brl.arpa (Doug Gwyn) writes:
>Some implementations of bcopy() and memcpy() do guarantee
>proper handling of overlapping fields.  But not all do, so one cannot
>count on it if one's trying to write truly portable code.  ANSI C will
>specify a new function memmove() with this property guaranteed.

I'll probably be disgusted by the answer, but can someone explain
why two functions are needed instead of one?  Why not just add
the guarantee to memcpy?  In my experience, it's not hard to
implement the correct, bidirectional copy behavior.  Did someone
actually manage to convince the committee that there is an
architecture and/or implementer out there that is so badly broken
that the overlap test would significantly slow down programs
which did not need the guarantee?  Or is it a code size issue for
potential in-line implementations?  (I am aware that a correct
overlap test is not trivial for badly broken architectures such
as the segmented 80x86, but the correct test on those machines is
not really hard or slow, either.)

                                            Steve Summit
                                            scs@adam.pika.mit.edu

gwyn@smoke.ARPA (Doug Gwyn ) (09/13/88)

In article <7039@bloom-beacon.MIT.EDU> scs@adam.pika.mit.edu (Steve Summit) writes:
>I'll probably be disgusted by the answer, but can someone explain
>why two functions are needed instead of one?  Why not just add
>the guarantee to memcpy?

(1) many people want a fast block-move, many want one that does the
"correct" thing on overlaps.  Two routines allows the application to
choose the trade-off.  A vendor could choose to make memcpy just
another entry point for memmove.

(2) it's possible that some existing (nonportable) applications depend
on the specific implementation of their current memcpy().

mmengel@cuuxb.ATT.COM (~XT4103000~Marc Mengel~C25~G25~6184~) (09/14/88)

In article <7039@bloom-beacon.MIT.EDU> scs@adam.pika.mit.edu (Steve Summit) writes:
>In article <8389@smoke.ARPA> gwyn@brl.arpa (Doug Gwyn) writes:
>>Some implementations of bcopy() and memcpy() do guarantee
>>proper handling of overlapping fields.  But not all do, so one cannot
>>count on it if one's trying to write truly portable code.  ANSI C will
>>specify a new function memmove() with this property guaranteed.
>
>I'll probably be disgusted by the answer, but can someone explain
>why two functions are needed instead of one?  Why not just add
>the guarantee to memcpy?  
>                                            Steve Summit

To check whether the source and destination overlap, you have to compare
two pointer values.  You can only do this legally ($3.3.8) if the two pointers 
point into the same array/aggregate.  Hence you need memmove() for
shifting items in an array, and memcpy() for moving items between arrays.
Using memmove() on items not in the same array is therefore not guaranteed
to work, as the comparison of pointers not in the same array/aggregate is
undefined.

The issue is that to make memcpy() work the way you want it to, you
need to define pointer semantics for comparison on pointers that don't
point into the same array/aggregate.  Feel free to post a definition
for these semantics, I am sure the various net.hackers out there can
name you a machine that your semantics don't make sense on; or force
pointers to be unusually large objects.
-- 
 Marc Mengel			       
 mmengel@cuuxb.att.com
 attmail!mmengel	
 {lll-crg|mtune|att}!cuuxb!mmengel

scjones@sdrc.UUCP (Larry Jones) (09/14/88)

In article <7039@bloom-beacon.MIT.EDU>, scs@athena.mit.edu (Steve Summit) writes:
> I'll probably be disgusted by the answer, but can someone explain
> why two functions are needed instead of one?  Why not just add
> the guarantee to memcpy?  In my experience, it's not hard to
> implement the correct, bidirectional copy behavior.  Did someone
> actually manage to convince the committee that there is an
> architecture and/or implementer out there that is so badly broken
> that the overlap test would significantly slow down programs
> which did not need the guarantee?  Or is it a code size issue for
> potential in-line implementations?  (I am aware that a correct
> overlap test is not trivial for badly broken architectures such
> as the segmented 80x86, but the correct test on those machines is
> not really hard or slow, either.)

All of the above.  Many machines have only a single block move instruction
which means that the "backwards" move has to be very inefficient and you
need to do a true overlap test (rather than a simple direction test).
That could add up to a lot of code to inline, but it would really hurt
to not inline if the overlap case never happens.  The easiest way for
the compiler to know for sure whether the overlap case ever happens is
to have different functions for the different cases.

Also, the committee received a number of letters noting that there are
some fairly common operations where memcpy is the inner loop and so
ANY slowdown would be unacceptable (e.g. block moves on bitmap displays).

----
Larry Jones                         UUCP: uunet!sdrc!scjones
SDRC                                      scjones@sdrc.uucp
2000 Eastman Dr.                    BIX:  ltl
Milford, OH  45150                  AT&T: (513) 576-2070
"Save the Quayles" - Mark Russell

henry@utzoo.uucp (Henry Spencer) (09/14/88)

In article <7039@bloom-beacon.MIT.EDU> scs@adam.pika.mit.edu (Steve Summit) writes:
>I'll probably be disgusted by the answer, but can someone explain
>why two functions are needed instead of one?  Why not just add
>the guarantee to memcpy? ...

The key observation is that in many cases the programmer knows that the
source and destination do not overlap, and it is difficult for the compiler
to figure this out except by checking it at run time.  This is particularly
significant if the compiler is doing inlining for efficiency and relatively
small amounts of data are being moved -- in such a case, the overlap check
may significantly hurt performance.  Since the older definitions of memcpy
explicitly said "if the operands overlap, no guarantees", it seemed sound
to make memcpy the fast-but-dangerous case and add a new function for the
slow-but-safe case.
-- 
NASA is into artificial        |     Henry Spencer at U of Toronto Zoology
stupidity.  - Jerry Pournelle  | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

karl@haddock.ima.isc.com (Karl Heuer) (09/14/88)

In article <2063@cuuxb.ATT.COM> mmengel@cuuxb.ATT.COM (Marc Mengel) writes:
>To check whether the source and destination overlap, you have to compare two
>pointer values.  You can only do this legally ($3.3.8) if the two pointers
>point into the same array/aggregate.

Watch it -- the first `you' refers to the implementation; the second refers to
the user.  Certainly the implementation is free to generate any code that
happens to work.

>Hence you need memmove() for shifting items in an array, and memcpy() for
>moving items between arrays.  Using memmove() on items not in the same array
>is therefore not guaranteed to work, as the comparison of pointers not in the
>same array/aggregate is undefined.

No, memmove() is guaranteed to work on *any* valid pointers.  What you've
really proved is that memmove() cannot be portably implemented in C.

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
Followups to comp.std.c.

henry@utzoo.uucp (Henry Spencer) (09/15/88)

In article <2063@cuuxb.ATT.COM> mmengel@cuuxb.UUCP (Marc W. Mengel) writes:
>The issue is that to make memcpy() work the way you want it to, you
>need to define pointer semantics for comparison on pointers that don't
>point into the same array/aggregate...

This is largely irrelevant, since the insides of memcpy will usually be
highly machine-specific anyway.
-- 
NASA is into artificial        |     Henry Spencer at U of Toronto Zoology
stupidity.  - Jerry Pournelle  | uunet!attcan!utzoo!henry henry@zoo.toronto.edu