cstringpointersbuffermemcpy

Why does memcpy into a buffer and a pointer to the buffer work the same?


Say I have the following code:

char buff[100] = {0};
char msg[] = "hello!";

memcpy(buff, msg, sizeof(msg));

OR

memcpy(&buff, msg, sizeof(msg));

Why do the two memcpy lines work exactly the same?

I expected that when &buff is used, it would copy the msg into the memory where the pointer itself that buff decays into is stored, not the memory that that pointer actually points to.

When I imagine the pointers like this:

&buff->buff->buff[0]

I can rationalize why they behave the same. But when I imagine the actual memory like this:

address        | value   | (name)
--------------  --------- ----------------
0x1000         | 'h'     | (buff[0])
0x1001         | 'e'     | (buff[1])
... etc
__________________________________________

0x5000-0x5008  | 0x1000  | (buf - char *)
__________________________________________

0x8000-0x8008  | 0x5000  | (&buf - char**)
__________________________________________

Now I cannot see why the msg is not written at address 0x5000 instead, overwriting the value 0x1000.


Solution

  • C 2018 6.3.2.1 3 says an array is converted to a pointer to its first element except when:

    So, in memcpy(&buff, msg, sizeof(msg)), buff is the operand of unary & and is not converted to a pointer. &buff gives a pointer to the array.

    In memcpy(buff, msg, sizeof(msg)), buff is converted to a pointer to its first element.

    The starting location of the first element and the starting location of the array are the same location. So &buff and buff have the same value, but different types. So data is copied to the same place in both calls.

    (Also note that the difference in types becomes irrelevant because the first parameter of memcpy is declared to be void * restrict, so both &buff and buff are converted to the same type before the call.)