Code snippets:portable memmove
From C
Many memmove attempts attempt to compare s1 and s2 with a relational operator such as < or >. Unfortunately, however, this is not really portable. In C99, for example, 6.5.8p5 implies that if the relational operators are used with objects that are not sub-objects (including sub-sub-objects, and so on) of the same ultimate parent object, then the behaviour is undefined.
/* Shao Miller, 2012 */
#include <stdio.h>
#include <stdlib.h>
void * pmemcpy(void * s1, const void * s2, size_t n);
void * pmemmove(void * s1, const void * s2, size_t n);
int main(void) {
char test1[] = "0123456789";
char test2[] = "ABCDEFGHIJ";
char * t1;
char * t2;
t1 = pmemmove(test1, test1 + 5, 5);
t2 = pmemmove(test2 + 5, test2, 5);
(void) t2;
printf("%s\n%s\n", t1, test2);
return EXIT_SUCCESS;
}
void * pmemcpy(void * s1, const void * s2, size_t n) {
unsigned char * dest;
const unsigned char * src;
if (!s1 || !s2 || !n)
return s1;
dest = s1;
src = s2;
while (n--)
*dest++ = *src++;
return s1;
}
/* Portability wins over performance, here */
void * pmemmove(void * s1, const void * s2, size_t n) {
unsigned char * dest;
const unsigned char * src;
const unsigned char * src_end;
if (!s1 || !s2 || !n || s1 == s2)
return s1;
dest = s1;
src = s2;
/* The only interesting case is where src < dest with overlap */
for (src_end = src + n; src < src_end; ++src) {
if (src == dest)
break;
}
/* Is src > dest or non-overlapping? */
if (src == src_end)
return pmemcpy(s1, s2, n);
/* Otherwise, src < dest with overlap */
dest += n;
src = src_end;
while (n--)
*dest-- = *src--;
return s1;
}
