P.S I am aware that memcpy should not be used to copy data to an overlapping memory address, and that memmove should be used instead.
Based on my understanding of memcpy, the function basically copies each byte from the source address to the destination address sequentially for a specified number of bytes. So in theory, given the code:
int main(void){
int arr[] = {1, 2, 3, 0, 0};
memcpy(arr + 1, arr, 3 * sizeof(arr[0]));
return 0;
}
Shouldn't the result be arr = {1, 1, 1, 1, 0} since arr[0] is copied to the next location, which is copied again etc. leading to all 1s?
The actual output, however, is arr = {1, 1, 2, 3, 0}; where the elements seems to be copied properly. Why does this happen? My best guess is that memcpy uses some sort of buffer to hold a copy of elements it is copying, and copies each byte in the buffer instead of the updated array to avoid corrupting subsequent values.
I also tried copying longer portions of arrays to see if something like an 8-byte buffer exist:
int arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 0, 0, 0, 0, 0, 0, 0};
memcpy(arr + 8, arr, 16*sizeof(arr[0]));
And the output is still coherent with the previous example: arr = {1, 2, 3, 4, 5, 6, 7, 8, 1, 2....15, 16};
memcpyuses some sort of buffer to hold a copy of elements it is copying, and copies each byte in the buffer instead of the updated array to avoid corrupting subsequent values. No,memcpywill allow corruption (because it copies bytes incrementing from low to high addresses) (i.e. copy is left-to-right).memmovestarts from the end (highest) addresses (i.e.ptr + len - 1) and then decrements the pointers (i.e. copy is right-to-left). It "does the right thing" and does not need an extra buffer.memmovewill always work, but it may be slower thanmemcpy, depending upon the implementation. So, if caller is sure there is no overlap,memcpyis preferred (for speed and better cache performance because the cache H/W assumes incrementing addresses if doing anticipatory/speculative prefetch). Becausememmoveworks backwards, this tends to [possibly] confuse/defeat the prefetchmemmovemay well work forwards instead.