I think I'm getting rusty, so please bare with me. I'll try to be brief.
Q1. When trying to copy buffers, say buf2 to buf1, does the following check suffice against aliasing?
if (buf2 >= buf1 && buf2 < buf1 + buf1size) {
// aliasing
}
Q2. If so, can we selectively use either memcopy()
or memmove()
depending on the case, like this?
// use memcpy() by default
void *(*funcp)(void *restrict, const void *restrict, size_t) = &memcpy;
// switch to memmove() when aliasing
if ( aliasing ) {
// this cast FORCEFULLY changes the type-qualifiers of the declared parameters
funcp = (void *(*)(void *, const void *, size_t)) &memmove;
}
// later on ...
if ( buf2size <= buf1size ) {
(*funcp)( buf1, buf2, buf2size ); // funcp() works too, I prefer making it explicit
}
It works but I'm not comfortable at all with forcefully casting the type-qualifiers of the parameters when switching to memmove()
. I think the standard confirms my doubts (can never find these darn things when I need them... using C99 btw), but since the code works I'd like to be extra sure, because if it's ok like that it would save me from duplicating buf2, work with the duplicate and freeing it when done.
For any two generic pointers, you can't really do pointer arithmetic on them. This is regulated by the additive operators C17 6.5.6/8:
Similar text exists for the relational operators (6.5.8) - any two pointers getting compared with them must point at the same array or otherwise the behavior is undefined.
You can in theory convert the pointers to integers in the form of
uintptr_t
and do arithmetic on that one. If you know for certain thatbuf1
points at the beginning of an array ofbuf1size
items, then you could in theory calculate ifbuf2
points at the same array or not, by doing integer arithmetic onuintptr_t
. But there isn't much to gain from that.Instead you could simply write your function as
And push the responsibility of ensuring that the two buffers don't alias onto the caller.
As for your function pointer selection of either
memcpy
ormemmove
, then apparently the mainstream compilers (gcc, clang) seem to ignore that one version hasrestrict
qualified pointers. If that's conforming behavior or not, I'm not sure.