David T. Ashley said:
This seems self-contradictory. If the caller can handle a
special case "just as easily," why is it "useful" to require the
internals of memcpy() to handle it in a particular way?
Please don't play Devil's Advocate because you are bored : ).
Creating a memcpy() function that doesn't handle the size=0 case is
just as silly as creating a square root function that calculates
square root for every non-negative integer except 0. [snip]
I think you're confusing implementation and specification.
I expect most implementations will work just fine for any pointer
values given to memcpy() when the number of bytes to be moved is
zero.
However, the specification is written considering all possible
implementations, including some that have hardware characteristics
we don't even know about yet. In light of that, it is natural to
give as much freedom as we can to implementors of library
functions like memcpy(), provided the burden on developers using
those functions isn't too high. Here the burden seems pretty low
-- in practice I expect most calls to memcpy() either are known to
have valid pointer arguments, or are inside an if() if the pointer
arguments might not be valid (and so the calls would not be made
if the pointer arguments were null, for example), ie, the tests
would be made anyway, independent of whether memcpy() always works
for zero length calls. Since the burden seems to be low, we give
implementations more latitude, because even though _most_ won't
need it, _some_ may find it a significant benefit. It's because
we don't know the characteristics of all implementations,
including future implementations, that it makes sense to keep
the specifications as unrestrictive as we reasonably can.