From this link: http://clc-wiki.net/wiki/memmove
#include <stddef.h> /* for size_t */
void *memmove(void *dest, const void *src, size_t n)
{
unsigned char *pd = dest;
const unsigned char *ps = src;
if (__np_anyptrlt(ps, pd))
for (pd += n, ps += n; n--;)
*--pd = *--ps;
else
while(n--)
*pd++ = *ps++;
return dest;
}
Is the use of __np_anyptrlt
redundant? Why not just use if (ps < pd)
?
The notes on the page you linked explains it:
__np_anyptrlt(p1, p2):
A macro or function such that, for any two pointers p1 and p2, __np_anyptrlt(p1,p2) evaluates to:
- non-zero if p1 and p2 point within the same object and p1 is less than p2
- zero if p1 and p2 point within the same object and p1 is greater than p2
- an unspecified integer value if the pointers don't point within the same object or if they compare equal.
A naive implementation is ((p1) < (p2)), but according to the Standard, 6.5.9 (N1124 numbering), this results in undefined behavior when p1 and p2 do not point within (or one member past the end of) a single array object. This naive implementation should only be used then by implementors who can ensure that the behaviour is always reasonable in those cases. The actual end value of the expression doesn't matter in those cases though because for distinct objects it's impossible to corrupt memory no matter which direction memmove iterates in.
So, it's only safe to use ps < pd
if your platform guarantees that comparisons between pointers into different arrays behave sanely. The standard says that such comparisons are undefined, and so an unhelpful compiler may create code that does anything at all (such as crashing, corrupting data, or making demons fly out of your nose).
It's probably likely that most compilers do something acceptable, but you'll need to consult your specific compiler's documentation to know for sure.