Here's a pointer/array example that gave me pause. Assume you have two arrays:
uint8_t source[16] = { /* some initialization values here */ };
uint8_t destination[16];
And your goal is to copy the uint8_t contents from source destination using memcpy(). Guess which of the following accomplish that goal:
memcpy(destination, source, sizeof(source));
memcpy(&destination, source, sizeof(source));
memcpy(&destination[0], source, sizeof(source));
memcpy(destination, &source, sizeof(source));
memcpy(&destination, &source, sizeof(source));
memcpy(&destination[0], &source, sizeof(source));
memcpy(destination, &source[0], sizeof(source));
memcpy(&destination, &source[0], sizeof(source));
memcpy(&destination[0], &source[0], sizeof(source));
The answer (Spoiler Alert!) is ALL of them. "destination", "&destination", and "&destination[0]" are all the same value. "&destination" is a different type than the other two, but it is still the same value. The same goes for the permutations of "source".
As an aside, I personally prefer the first version.