There's no particular reason in this specific case, it's mostly stylistic.
But in general it is always best to stick to unsigned arithmetic when dealing with raw data. That is: unsigned char
or uint8_t
.
The char
type is problematic because it has implementation-defined signedness and is therefore avoided in such code. Is char signed or unsigned by default?
NOTE: this is dangerous and poor style:
char *src_arr = (char *)src;
(And the cast hid the problem underneath the carpet)
Since you correctly used "const correctness" for src
, the correct type is: const char *src_arr;
I'd change to code to:
unsigned char *dest_arr = dest;
const unsigned char *src_arr = src;
A good rule of thumb for beginners is to never use a cast. I'm serious. Some 90% of all casts we see on SO in beginner-level programs are wrong, in one way or the other.
Btw (advanced topic) there's a reason why memcpy
has the prototype as:
void *memcpy(void * restrict s1,
const void * restrict s2,
size_t n);
The restrict
qualifier on the pointers tell the user of the function "hey I'm counting on you to not pass on two pointers to the same object or pointers that may overlap". Doing so would cause problems in various situations and for various targets, so this is a good idea.
It's much more likely that the user passes on overlapping pointers than null pointers, so if you are to have slow, superfluous error checking against NULL
, you should also restrict
qualify the pointers.
If the user passes on null pointers I'd just let the function crash, instead of slowing it down with extra branches that are pointless bloat in some 99% of all use cases.