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.
C 2018 6.3.2.1 3 says an array is converted to a pointer to its first element except when:
sizeof
,&
, orSo, 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.)